возвращение строки из dllexport функции
От: romstyop  
Дата: 27.11.03 09:29
Оценка:
Привет All!
Такая проблема.
Код в dll VC6:
extern "C" __declspec(dllexport) BOOL ProcessD(LPCSTR FileName, LPSTR &pStrBuffer)
{
    BOOL bResult = FALSE;
    char buffer[1024];
    CElaboration *pMot = new CElaboration(FileName);
    if (pMot != NULL)
    {
        bResult = motore->Decriptare(buffer);    
        strcpy(pStrBuffer,buffer);
        delete pMot;
        pMot = NULL;
    }
    return bResult;
}


и есть GUI на VB:
Private Declare Function ProcessD Lib "mydll.dll" (ByVal FileName As String, ByRef strBuffer As String) As Integer

Label1.Caption = CStr(ProcessD("myfile.dat", str))


При debug dll выдается следующее:
HEAP[test.exe]: Heap block at 0014E2F8 modified at 0014E310 past requested size of 10
HEAP[test.exe]: Invalid Address specified to RtlSizeHeap( 00140000, 0014E300 )

Подскажите, как правильно возвратить строку, плиз.

Исправлена подсветка синтаксиса. -- ПК.
27.11.03 18:11: Перенесено модератором из 'C/C++' — ПК
Re: возвращение строки из dllexport функции
От: Leonid V. Volnin Россия  
Дата: 27.11.03 09:52
Оценка:
Здравствуйте, romstyop, Вы писали:

R>Привет All!

R>Такая проблема.
R>Код в dll VC6:
R>extern "C" __declspec(dllexport) BOOL ProcessD(LPCSTR FileName, LPSTR &pStrBuffer)
[skipped]
R>и есть GUI на VB:
R>Private Declare Function ProcessD Lib "mydll.dll" (ByVal FileName As String, ByRef strBuffer As String) As Integer

R>Label1.Caption = CStr(ProcessD("myfile.dat", str))


R> При debug dll выдается следующее:

R>HEAP[test.exe]: Heap block at 0014E2F8 modified at 0014E310 past requested size of 10
R>HEAP[test.exe]: Invalid Address specified to RtlSizeHeap( 00140000, 0014E300 )

R>Подскажите, как правильно возвратить строку, плиз.


Попробуй вместо LPSTR использовать тип VARIANT (с типом BSTR). С "вариантом" Бейсик работает нормально.
З.Ы. Естественно, что буфер под строку надо выделять в ProcessD .
best regards, Leonid
Re[2]: возвращение строки из dllexport функции
От: romstyop  
Дата: 27.11.03 10:54
Оценка:
Здравствуйте, Leonid V. Volnin, Вы писали:

LVV>Здравствуйте, romstyop, Вы писали:


R>>Привет All!

R>>Такая проблема.
R>>Код в dll VC6:
R>>extern "C" __declspec(dllexport) BOOL ProcessD(LPCSTR FileName, LPSTR &pStrBuffer)
LVV>[skipped]
R>>и есть GUI на VB:
R>>Private Declare Function ProcessD Lib "mydll.dll" (ByVal FileName As String, ByRef strBuffer As String) As Integer

R>>Label1.Caption = CStr(ProcessD("myfile.dat", str))


R>> При debug dll выдается следующее:

R>>HEAP[test.exe]: Heap block at 0014E2F8 modified at 0014E310 past requested size of 10
R>>HEAP[test.exe]: Invalid Address specified to RtlSizeHeap( 00140000, 0014E300 )

R>>Подскажите, как правильно возвратить строку, плиз.


LVV>Попробуй вместо LPSTR использовать тип VARIANT (с типом BSTR). С "вариантом" Бейсик работает нормально.

LVV>З.Ы. Естественно, что буфер под строку надо выделять в ProcessD .

Сделал так:
extern "C" __declspec(dllexport) BOOL CALLBACK ProcessD(LPCSTR FileName, VARIANT FAR*pVar)
{
BOOL bResult = FALSE;
CString sBuffer;
CElaboration *motore = new CElaboration(FileName);
if (motore != NULL)
{
bResult = motore->Decriptare(sBuffer);
VariantClear(pVar);
pVar->vt = VT_BSTR;
pVar->bstrVal = sBuffer.AllocSysString();
sBuffer.ReleaseBuffer();
delete motore;
motore = NULL;
}
return bResult;
}
Проблема осталась .
Re[3]: возвращение строки из dllexport функции
От: Denwer Россия  
Дата: 27.11.03 10:58
Оценка:
Здравствуйте, romstyop, Вы писали:

R>Здравствуйте, Leonid V. Volnin, Вы писали:


LVV>>Здравствуйте, romstyop, Вы писали:


Можно попробовать так
extern "C" __declspec(dllexport) BOOL CALLBACK ProcessD(LPCSTR FileName, CComBSTR& pVar)


Для VC7 можно и обычный стринг использовать
extern "C" __declspec(dllexport) BOOL CALLBACK ProcessD(LPCSTR FileName, CString& pVar)
Re[4]: возвращение строки из dllexport функции
От: Denwer Россия  
Дата: 27.11.03 11:00
Оценка:
Здравствуйте, Denwer, Вы писали:

D>Здравствуйте, romstyop, Вы писали:


R>>Здравствуйте, Leonid V. Volnin, Вы писали:


LVV>>>Здравствуйте, romstyop, Вы писали:


D>Можно попробовать так

D>
D>extern "C" __declspec(dllexport) BOOL CALLBACK ProcessD(LPCSTR FileName, CComBSTR& pVar)
D>


D>Для VC7 можно и обычный стринг использовать

D>
D>extern "C" __declspec(dllexport) BOOL CALLBACK ProcessD(LPCSTR FileName, CString& pVar)
D>


Упс, извеняюсь, не заметил что клиент на бейсике, тогда попробуй так
extern "C" __declspec(dllexport) BOOL CALLBACK ProcessD(BSTR FileName, BSTR* pVar)
Re[5]: возвращение строки из dllexport функции
От: romstyop  
Дата: 27.11.03 11:16
Оценка:
Здравствуйте, Denwer, Вы писали:

D>Здравствуйте, Denwer, Вы писали:


D>>Здравствуйте, romstyop, Вы писали:


R>>>Здравствуйте, Leonid V. Volnin, Вы писали:


LVV>>>>Здравствуйте, romstyop, Вы писали:


D>>Можно попробовать так

D>>
D>>extern "C" __declspec(dllexport) BOOL CALLBACK ProcessD(LPCSTR FileName, CComBSTR& pVar)
D>>


D>>Для VC7 можно и обычный стринг использовать

D>>
D>>extern "C" __declspec(dllexport) BOOL CALLBACK ProcessD(LPCSTR FileName, CString& pVar)
D>>


D>Упс, извеняюсь, не заметил что клиент на бейсике, тогда попробуй так

D>
D>extern "C" __declspec(dllexport) BOOL CALLBACK ProcessD(BSTR FileName, BSTR* pVar)
D>


Я пользую VC6 и
если брать CComBSTR or BSTR в VB получаю:
str = "mXyX XsXtXrXiXnXgX"
где X= \n (наверное, т.к. отображается в Debug в виде квадратика)
Re[6]: возвращение строки из dllexport функции
От: Leonid V. Volnin Россия  
Дата: 27.11.03 11:57
Оценка: 2 (1)
Здравствуйте, romstyop, Вы писали:

[skipped]
R>Я пользую VC6 и
R>если брать CComBSTR or BSTR в VB получаю:
R> str = "mXyX XsXtXrXiXnXgX"
R> где X= \n (наверное, т.к. отображается в Debug в виде квадратика)

Это потому, что строка в unicode, т.е. на каждый символ по два байта.
str = {'m',0,'y',0,32,0,'s',0,'t',0,'r',0,'i',0,'n',0,'g',0};
best regards, Leonid
Re[7]: возвращение строки из dllexport функции
От: romstyop  
Дата: 27.11.03 12:16
Оценка:
Здравствуйте, Leonid V. Volnin, Вы писали:

LVV>Здравствуйте, romstyop, Вы писали:


LVV>[skipped]

R>>Я пользую VC6 и
R>>если брать CComBSTR or BSTR в VB получаю:
R>> str = "mXyX XsXtXrXiXnXgX"
R>> где X= \n (наверное, т.к. отображается в Debug в виде квадратика)

LVV>Это потому, что строка в unicode, т.е. на каждый символ по два байта.

LVV>
LVV>str = {'m',0,'y',0,32,0,'s',0,'t',0,'r',0,'i',0,'n',0,'g',0};
LVV>


Да, я в курсе, но как ее загрузить в String на VB, я получаю str = "m"
Ведь через СОМ [out, retval] BSTR *pVal все возвращается нормально!!!
Re[8]: возвращение строки из dllexport функции
От: Denwer Россия  
Дата: 27.11.03 12:57
Оценка:
Здравствуйте, romstyop, Вы писали:

R>Здравствуйте, Leonid V. Volnin, Вы писали:


LVV>>Здравствуйте, romstyop, Вы писали:


LVV>>[skipped]

R>>>Я пользую VC6 и
R>>>если брать CComBSTR or BSTR в VB получаю:
R>>> str = "mXyX XsXtXrXiXnXgX"
R>>> где X= \n (наверное, т.к. отображается в Debug в виде квадратика)

LVV>>Это потому, что строка в unicode, т.е. на каждый символ по два байта.

LVV>>
LVV>>str = {'m',0,'y',0,32,0,'s',0,'t',0,'r',0,'i',0,'n',0,'g',0};
LVV>>


R>Да, я в курсе, но как ее загрузить в String на VB, я получаю str = "m"

R>Ведь через СОМ [out, retval] BSTR *pVal все возвращается нормально!!!
Так и должно быть.

Но токо вот мне не понятно почему не работает LPSTR ?
Может попробуешь все же с
extern "C" __declspec(dllexport) BOOL ProcessD(LPCSTR FileName, LPSTR pStrBuffer)

Я не знаю как там в бейсике идет объявление, но может всетаки там есть ошибка у тебя?
Re[9]: возвращение строки из dllexport функции
От: romstyop  
Дата: 27.11.03 14:27
Оценка:
Здравствуйте, Denwer, Вы писали:

D>Здравствуйте, romstyop, Вы писали:


R>>Здравствуйте, Leonid V. Volnin, Вы писали:


LVV>>>Здравствуйте, romstyop, Вы писали:


LVV>>>[skipped]

R>>>>Я пользую VC6 и
R>>>>если брать CComBSTR or BSTR в VB получаю:
R>>>> str = "mXyX XsXtXrXiXnXgX"
R>>>> где X= \n (наверное, т.к. отображается в Debug в виде квадратика)

LVV>>>Это потому, что строка в unicode, т.е. на каждый символ по два байта.

LVV>>>
LVV>>>str = {'m',0,'y',0,32,0,'s',0,'t',0,'r',0,'i',0,'n',0,'g',0};
LVV>>>


R>>Да, я в курсе, но как ее загрузить в String на VB, я получаю str = "m"

R>>Ведь через СОМ [out, retval] BSTR *pVal все возвращается нормально!!!
D>Так и должно быть.

D>Но токо вот мне не понятно почему не работает LPSTR ?

D>Может попробуешь все же с
D>
D>extern "C" __declspec(dllexport) BOOL ProcessD(LPCSTR FileName, LPSTR pStrBuffer)
D>

D>Я не знаю как там в бейсике идет объявление, но может всетаки там есть ошибка у тебя?

Уже юзал. В VB:
Private Declare Function ProcessD Lib "mydll.dll" (ByVal FileName As String, ByRef strBuffer As Variant) As Integer

Label1.Caption = CStr(ProcessD(App.Path & "\spe1.xml", str))
'str = {'m',0,'y',0,32,0,'s',0,'t',0,'r',0,'i',0,'n',0,'g',0};
MsgBox str
'msgbox = "m"
Re: возвращение строки из dllexport функции
От: Vi2 Удмуртия http://www.adem.ru
Дата: 28.11.03 05:23
Оценка:
Здравствуйте, romstyop, Вы писали:

Начну с того, что через Private Declare Sub/Function ... Lib "..." вызываются функции, которые НЕ предназначены для работы с СОМом. Даже если волею случая они имееют соглашение __stdcall и таким образом могут вызваться из-под VB. Чтобы иметь возможность вызова ТАКИХ функций VB использует другую стратегию по параметрам, содержащим строки.

ByVal FileName As String приводит к передаче внутреннего буфера, приведенного к char* и конвертируемого при возврате обратно. Как это делает функция SysAllocStringByteLen. Т.е. параметр IDL описывался бы так [in,out,string] char* FileName (ЭТО ТОЛЬКО АНАЛОГИЯ, а не реальное положение дел).

Резюме: Такой параметр можно принять в LPSTR или BSTR, но иметь в виду, что менять строку нужно в char-ах и в размерах, возвращаемых функциями strlen или SysStringByteLen.

ByRef strBuffer As String приводит к передаче адреса из вышеуказанного.

Резюме: Такой параметр можно принять в LPSTR * или BSTR *, но иметь в виду, что менять строку нужно в char-ах и в размерах, возвращаемых функциями strlen или SysStringByteLen. А если изменять выделение памяти, то пользоваться функциями выделения OLE строк, но с учетом их char характера.

Private Declare Function ProcessD Lib "mydll.dll" (ByVal FileName As String, ByRef strBuffer As String) As Integer

Label1.Caption = ProcessD("myfile.dat", str)


extern "C" __declspec(dllexport) __stdcall BOOL ProcessD(LPCSTR FileName, LPSTR * pStrBuffer)
{
...
    CElaboration *pMot = new CElaboration(FileName);
...
    if( *pStrBuffer )
        ::SysFreeString( (BSTR) *pStrBuffer ); // освободить старое значение если такое имеется
    *pStrBuffer = (LPSTR) ::SysAllocStringByteLen( buffer, 1024 или strlen(buffer) );
}


PS
Жуткое зрелище. Бр-р-р. Но что есть то есть.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[8]: StrConv
От: Vi2 Удмуртия http://www.adem.ru
Дата: 28.11.03 05:29
Оценка: 3 (1)
Здравствуйте, romstyop, Вы писали:

R>Да, я в курсе, но как ее загрузить в String на VB, я получаю str = "m"
R>Ведь через СОМ [out, retval] BSTR *pVal все возвращается нормально!!!

Можно использовать str = StrConv(str, vbFromUnicode)
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.