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++' — ПК
Здравствуйте, 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 .
Здравствуйте, 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;
}
Проблема осталась .
Здравствуйте, Denwer, Вы писали:
D>Здравствуйте, romstyop, Вы писали:
R>>Здравствуйте, Leonid V. Volnin, Вы писали:
LVV>>>Здравствуйте, romstyop, Вы писали:
D>Можно попробовать так D>
Здравствуйте, Denwer, Вы писали:
D>Здравствуйте, Denwer, Вы писали:
D>>Здравствуйте, romstyop, Вы писали:
R>>>Здравствуйте, Leonid V. Volnin, Вы писали:
LVV>>>>Здравствуйте, romstyop, Вы писали:
D>>Можно попробовать так D>>
[skipped] R>Я пользую VC6 и R>если брать CComBSTR or BSTR в VB получаю: R> str = "mXyX XsXtXrXiXnXgX" R> где X= \n (наверное, т.к. отображается в Debug в виде квадратика)
Это потому, что строка в unicode, т.е. на каждый символ по два байта.
Здравствуйте, 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>
Здравствуйте, 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>>
R>Да, я в курсе, но как ее загрузить в String на VB, я получаю str = "m" R>Ведь через СОМ [out, retval] BSTR *pVal все возвращается нормально!!!
Так и должно быть.
Но токо вот мне не понятно почему не работает LPSTR ?
Может попробуешь все же с
Здравствуйте, 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>>>
R>>Да, я в курсе, но как ее загрузить в String на VB, я получаю str = "m" R>>Ведь через СОМ [out, retval] BSTR *pVal все возвращается нормально!!! D>Так и должно быть.
D>Но токо вот мне не понятно почему не работает LPSTR ? D>Может попробуешь все же с D>
Начну с того, что через 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) );
}