Subject | RE: [Firebird-Architect] XSQLDA/XSQLVAR issues |
---|---|
Author | Samofatov, Nickolay |
Post date | 2005-02-02T17:45:12Z |
Jim,
previous letter: one with no destructor call and one with crash.
Here is the sample kindly provided by Vlad and slightly modified by me
to demonstrate the problem better.
Delphi/Win32 code:
-----------------------------------------------
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
Type
ECallbackException = class (Exception)
constructor Create(ErrCode : Integer);
end;
TCallback = procedure (ErrCode : Integer); stdcall;
{ ECallbackException }
constructor ECallbackException.Create(ErrCode: Integer);
begin
inherited Create('CallbackError : ' + IntToStr(ErrCode));
end;
procedure callbackRaiseError(ErrCode : Integer); stdcall;
begin
raise ECallbackException.Create(ErrCode);
end;
function ExternalAPI : Integer; stdcall; external
'ExceptTest.dll';
procedure SetCallback(Callback : TCallback); stdcall; external
'ExceptTest.dll';
begin
try
WriteLn('SetCallback');
SetCallback(callbackRaiseError);
Write('Call API...');
WriteLn('return', ExternalAPI);
ReadLn;
except
on E:Exception do
begin
WriteLn;
WriteLn('Exception [', E.ClassName, '] : ', E.Message);
ReadLn;
end;
end
end.
-----------------------------------------------
C++ source, please compile it to DLL using current MinGW, I used the
command:
g++.exe -shared -o ExceptTest.dll test.cpp
-----------------------------------------------
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
typedef void (__stdcall *fn_except_callback)(int) ;
fn_except_callback except_callback = 0;
void throwError(int code)
{
if(except_callback)
(*except_callback)(code);
}
class CSimple
{
public:
CSimple()
{
printf("CSimple\n\r");
}
~CSimple()
{
printf("~CSimple\n\r");
}
static void func() {
CSimple a;
throwError(15);
}
};
extern "C" {
void __declspec(dllexport) SetCallback(fn_except_callback callback)
{
except_callback = callback;
}
int __declspec(dllexport) ExternalAPI(void)
{
CSimple::func();
return 0;
}
}
-----------------------------------------------
If you run Project1.exe you'll notice that destructor for CSimple is not
getting called.
> If you can find any system were caller links or load loadsI can think of many such systems. I named two such environments in my
> and the subsequent unwind either blows up or fails to call
> the Lib destructor, then I will have to rethink my strategy.
previous letter: one with no destructor call and one with crash.
Here is the sample kindly provided by Vlad and slightly modified by me
to demonstrate the problem better.
Delphi/Win32 code:
-----------------------------------------------
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
Type
ECallbackException = class (Exception)
constructor Create(ErrCode : Integer);
end;
TCallback = procedure (ErrCode : Integer); stdcall;
{ ECallbackException }
constructor ECallbackException.Create(ErrCode: Integer);
begin
inherited Create('CallbackError : ' + IntToStr(ErrCode));
end;
procedure callbackRaiseError(ErrCode : Integer); stdcall;
begin
raise ECallbackException.Create(ErrCode);
end;
function ExternalAPI : Integer; stdcall; external
'ExceptTest.dll';
procedure SetCallback(Callback : TCallback); stdcall; external
'ExceptTest.dll';
begin
try
WriteLn('SetCallback');
SetCallback(callbackRaiseError);
Write('Call API...');
WriteLn('return', ExternalAPI);
ReadLn;
except
on E:Exception do
begin
WriteLn;
WriteLn('Exception [', E.ClassName, '] : ', E.Message);
ReadLn;
end;
end
end.
-----------------------------------------------
C++ source, please compile it to DLL using current MinGW, I used the
command:
g++.exe -shared -o ExceptTest.dll test.cpp
-----------------------------------------------
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
typedef void (__stdcall *fn_except_callback)(int) ;
fn_except_callback except_callback = 0;
void throwError(int code)
{
if(except_callback)
(*except_callback)(code);
}
class CSimple
{
public:
CSimple()
{
printf("CSimple\n\r");
}
~CSimple()
{
printf("~CSimple\n\r");
}
static void func() {
CSimple a;
throwError(15);
}
};
extern "C" {
void __declspec(dllexport) SetCallback(fn_except_callback callback)
{
except_callback = callback;
}
int __declspec(dllexport) ExternalAPI(void)
{
CSimple::func();
return 0;
}
}
-----------------------------------------------
If you run Project1.exe you'll notice that destructor for CSimple is not
getting called.
> Jim StarkeyNickolay