вызов функции из длл на дельфи (и исключения при этом )
От: Lecha  
Дата: 13.05.04 18:46
Оценка:
Приветствую,
такая вот проблема:
есть dll на дельфи (без исходников), листочек документации к ней(прототипы функций) и небольшой примерчик тоже на дельфи, который эту dll вызывает.

//прототип из документации
procedure connect(hostName, portNumber: PChar); stdcall; external CustomDll;


//кусок из примерчика
...
begin
try
connect(PChar(EditHost.Text), PChar(EditPort.Text));
except
On E: Exception do
begin
S := getExceptionInfo(E); //see below
writeln(S);
raise Exception.Create(S);
end;
end;
end;

//там же из примечика
function getExceptionInfo(E: Exception): PChar;
var
S: String;
buf: array[0..512] of char;
begin
S := E.ClassName + ', ' + E.Message;
StrLCopy(buf, PChar(S), SizeOf(buf));
Result := buf;
end;


все работает замечательно (примерчик на дельфи то есть), когда правильные параметры даешь(адрес и порт) то просходит коннект, если же неправильные — генерится исключение (таймаут) и красиво пишется как в консольное окошко так и в мевсседжбокс.

Теперь мне надо позвать эту функцию из VC++ 6.0 (и исключения обработать)
мой код:



...
typedef void (_stdcall * LPconnect)(LPTSTR,LPTSTR);

HINSTANCE hDLL; // Handle to DLL
LPconnect pconnect; // Function pointer

hDLL = LoadLibrary("customdll.dll");

if (hDLL != NULL)
{
pconnect= (LPconnect )GetProcAddress(hDLL,
"connect ");
if (!pconnect)
{
// handle the error
FreeLibrary(hDLL); 

}
else
{
try
{
// call the function

pconnect (_T("aaa"),_T("bbb"));

}
catch(CException * e)
{


e->ReportError();
e->Delete();

}
}



вроде выглядит нормально,(хандле от длльки и указатель на функцию валидные),
но при выполнениии "unchandled exception" (причем в обоих случаях, т.е когда правильные и когда неправильные параметры)
получается , что CException и все порожденные мы не ловим.


// меняю catch блок на
catch(...)
{
ASSERT(FALSE);
}


теперь нормально, попадаю в catch, но никакойиформации об исключении получить нельзя (а может можно? как?)
пробовал применитиь структурную систему



//вот так примерно
DWORD FilterFunction(LPEXCEPTION_POINTERS pe) 
{ 
ASSERT(pe->ExceptionRecord->ExceptionCode);
return EXCEPTION_EXECUTE_HANDLER; 
} 
.....


__try
{
// call the function
pconnect (_T("aaa"),_T("bbb"));
}
__except ((FilterFunction(GetExceptionInformation()))
{
ASSERT(FALSE); 
}


также ловится( точка останова на return EXCEPTION_EXECUTE_HANDLER; )
при этом
pe->ExceptionRecord->ExceptionCode = 0x0eedfade (стабильно)
и
pe->ExceptionRecord->NumberParameters=7;
pe->ExceptionRecord->ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]также семь заполнено

нигде не нашел, что значит 0x0eedfade, а также как достать строчку для месседжа отсюда (ExceptionInformation???)

короче я в тупике,

кто то мжет делал примерно такоеже, что я пропустил?
проблема в том что имею предубеждение к дельфям, поэтому не ориентируюсь там совсем,
stdcall в дельфях имеет другой смысл? PChar это не LPTSTR?
у кого какие идеи?
заранее благодарен
Re: вызов функции из длл на дельфи (и исключения при этом )
От: SchweinDeBurg Россия https://zarezky.spb.ru/
Дата: 13.05.04 19:08
Оценка: +2
Здравствуйте, Lecha, Вы писали:

L>Приветствую,

L>такая вот проблема:
L>есть dll на дельфи (без исходников), листочек документации к ней(прототипы функций) и небольшой примерчик тоже на дельфи, который эту dll вызывает.

L>//прототип из документации

L>procedure connect(hostName, portNumber: PChar); stdcall; external CustomDll;

L>
L>//кусок из примерчика
L>...
L>begin
L>try
L>connect(PChar(EditHost.Text), PChar(EditPort.Text));
L>except
L>On E: Exception do
L>begin
L>S := getExceptionInfo(E); //see below
L>writeln(S);
L>raise Exception.Create(S);
L>end;
L>end;
L>end;

L>//там же из примечика
L>function getExceptionInfo(E: Exception): PChar;
L>var
L>S: String;
L>buf: array[0..512] of char;
L>begin
L>S := E.ClassName + ', ' + E.Message;
L>StrLCopy(buf, PChar(S), SizeOf(buf));
L>Result := buf;
L>end;
L>


L>все работает замечательно (примерчик на дельфи то есть), когда правильные параметры даешь(адрес и порт) то просходит коннект, если же неправильные — генерится исключение (таймаут) и красиво пишется как в консольное окошко так и в мевсседжбокс.


Что естественно — исключение Object Pascal ловится кодом Object Pascal.

L>Теперь мне надо позвать эту функцию из VC++ 6.0 (и исключения обработать)

L>мой код:

L>
L>...
L>try
L>{
L>// call the function
L>   pconnect (_T("aaa"),_T("bbb"));
L>}
L>catch(CException * e)
L>{
L>   e->>ReportError();
L>   e->>Delete();
L>}
L>


L>вроде выглядит нормально,(хандле от длльки и указатель на функцию валидные),

L>но при выполнениии "unchandled exception" (причем в обоих случаях, т.е когда правильные и когда неправильные параметры)
L>получается , что CException и все порожденные мы не ловим.

Совершенно верно — MFC-шный CException к дельфийскоу Exception никакого отношения не имеет.

L>
L>// меняю catch блок на
L>catch(...)
L>{
L>ASSERT(FALSE);
L>}
L>


L>теперь нормально, попадаю в catch, но никакойиформации об исключении получить нельзя (а может можно? как?)


Сомневаюсь я, что можно получить информацию об исключении брошенном из Object Pascal, поймав его в коде на C++, не используя никаких "хаков".

L>пробовал применитиь структурную систему


L>
L>//вот так примерно
L>DWORD FilterFunction(LPEXCEPTION_POINTERS pe) 
L>{ 
L>ASSERT(pe->ExceptionRecord->ExceptionCode);
L>return EXCEPTION_EXECUTE_HANDLER; 
L>} 
L>.....

L>__try
L>{
L>// call the function
L>pconnect (_T("aaa"),_T("bbb"));
L>}
L>__except ((FilterFunction(GetExceptionInformation()))
L>{
L>ASSERT(FALSE); 
L>}

L>


L>также ловится( точка останова на return EXCEPTION_EXECUTE_HANDLER; )

L>при этом
pe->>ExceptionRecord->ExceptionCode = 0x0eedfade (стабильно)

Знакомое число какое-то... а что при этом в окошке отладчика написано?

L>и

pe->>ExceptionRecord->NumberParameters=7;
pe->>ExceptionRecord->ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]также семь заполнено

L>проблема в том что имею предубеждение к дельфям, поэтому не ориентируюсь там совсем,


А вот это зря — "врагов нужно изучать"! (большая просьба ко всем — не цепляться к слову "враги" и не начинать флейм на тему "C++ vs. Delphi ).

L>stdcall в дельфях имеет другой смысл? PChar это не LPTSTR?

Нет, это там такое же, разве что декорация имен может отличаться от MSVC. И PChar это скорее все-таки LPSTR (без T).

L>у кого какие идеи?


ИМХО, самое надежное (чтобы без хакерства и асма) — написать на Delphi еще одну DLL, которая будет выполнять роль заглушки, вызывая бросающий исключения код, отлавливая эти исключения и передавая информацию о них "наверх" в гарантированно совместимой форме (в самодельной структуре, например... WNDCLASS — он-то везде WNDCLASS, что у "них", что у нас). И уже эту заглушку дергать из плюсового кода.
[ posted via RSDN@Home 1.1.2 stable ]
- Искренне ваш, Поросенок Пафнутий
Re[2]: вызов функции из длл на дельфи (и исключения при этом
От: Аноним  
Дата: 18.05.04 10:13
Оценка:
Здравствуйте, SchweinDeBurg, Вы писали:

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


L>>Приветствую,

L>>такая вот проблема:
L>>есть dll на дельфи (без исходников), листочек документации к ней(прототипы функций) и небольшой примерчик тоже на дельфи, который эту dll вызывает.
...
L>>теперь нормально, попадаю в catch, но никакойиформации об исключении получить нельзя (а может можно? как?)

SDB>Сомневаюсь я, что можно получить информацию об исключении брошенном из Object Pascal, поймав его в коде на C++, не используя никаких "хаков".


Думаю в данном случае можно позволить себе немного "хака"

...
L>>у кого какие идеи?

EXCEPTION_RECORD SavedExceptRec;
__try
{
// call the function
pconnect (_T("aaa"),_T("bbb"));
}
__except(SavedExceptRec = *(GetExceptionInformation())->ExceptionRecord, EXCEPTION_EXECUTE_HANDLER)
{
if (SavedExceptRec.ExceptionCode == 0x0eedfade) {
char **msg = (char**) SavedExceptRec.ExceptionInformation[1] + 1;
/*
0x0eedfade описан как cDelphiException и тогда второй элемент массива ExceptionInformation это адрес дельфийского объекта Exception. Первые четыре байта это ссылка на класс, следующие байты это адрес строки с сообщением исключения (динамические строки в delphi заканчиваются \0).
*/
MessageBox(NULL, *msg, NULL, MB_OK);
} else {...}
}

А вообще выбрасывать необработанные исключения в библиотеках не хорошо

18.05.04 14:21: Перенесено из 'C/C++'
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.