Reputation: 1
I have a problem with dll that contains procedure with Firebird TIBScript.
uses
System.SysUtils,
System.Classes,
DLLMainData in 'DLLMainData.pas' {DataModule2: TDataModule};
{$R *.res}
Procedure RunScript();stdcall;
begin
TDataModule2.RunScriptProc;
end;
exports
RunScript;
begin
end.
dll procedure
class function TDataModule2.RunScriptProc: boolean;
begin
with self.Create(nil) do
begin
try
IBDatabase1.Open;
IBScript1.ExecuteScript;
finally
IBDatabase1.Close;
Free;
end;
end;
end;
Now I call this procedure from an exe as follows:
procedure TForm2.Button1Click(Sender: TObject);
var
Handle: Integer;
LibraryProc :procedure();stdcall;
begin
Handle := LoadLibrary('dllka.dll');
if Handle <> 0 then
begin
try
LibraryProc := GetProcAddress(Handle,'RunScript');
if @LibraryProc = nil then
raise Exception.Create('erorr')
else
LibraryProc();
finally
Showmessage('Before free library');
FreeLibrary(Handle);
Handle := 0;
LibraryProc := nil
end
end;
Showmessage('ok');
end;
When TIBScript raise exception while executing (problem with sql etc.) in main App (witch this procedrue is calling from) hangs on FreeLibrary(). When Script was executed without problems everything works fine. I create small example because i thought that problem was with passing params to library but it is not.
Appreciate any assistance. I am using Delphi XE2. Thanks
Upvotes: 0
Views: 3096
Reputation: 962
@David Heffemen is correct. You cannot throw an exception from a DLL, but you can exit with an ExitCode if your intention is to exit the DLL when Delphi catches an exception.
I inherited code that was raising an exception when the DLL could not load, but was just hanging when the DLL could not be found. I solved it checking that the file exists and the handle was assigned, setting ExitCode to 1, and exiting. It produced a nice exception in my C# when I called an exported function:
procedure LoadMyDll();
begin
if (FileExists(MY_DLL_NAME)) then
_hMy32Dll := LoadLibrary(PChar(MY_DLL_NAME));
if (_hMy32Dll = 0) then
begin
System.ExitCode:=1;
exit;
end;
end;
The Exception message in C# was:
System.DllNotFoundException: Unable to load DLL 'C:\src\MyDLL\Delphi\Win32\Debug\MyDLL.dll': A dynamic link library (DLL) initialization routine failed. (Exception from HRESULT: 0x8007045A)
at MyDLLTest.Program.Min(Int32 x, Int32 y)
at MyDLLTest.Program.Main(String[] args) in C:\src\MyDLL\CSharp\MyDLLTest\MyDLLTest\Program.cs:line 23
Upvotes: 0
Reputation: 612964
A DLL is contracted not to throw exceptions out of exported functions. Your DLL breaks this contract.
Fix the problem by handling all exceptions in any exported function. Convert those exceptions into, for instance, an error code return value. This is one of the few times that it is reasonable to use an indiscriminate catch-all exception handler.
Your exported function would look like this:
function RunScript: Integer; stdcall;
begin
Try
TDataModule2.RunScriptProc;
Result := ERROR_CODE_SUCCESS;
Except
Result := ...; // your code to convert exception to error code goes here
End;
end;
Upvotes: 4