Subject RE: [Firebird-Architect] XSQLDA/XSQLVAR issues
Author Samofatov, Nickolay
Jim,

> If you can find any system were caller links or load loads
> and the subsequent unwind either blows up or fails to call
> the Lib destructor, then I will have to rethink my strategy.

I can think of many such systems. I named two such environments in my
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 Starkey

Nickolay