A very common topic in newsgroups is Dll Exception handling. If your dll raises an exception, the exception handler in the host app should not be able to recognize the class of the exception it trapped. That's because the host application doesn't recognizes the exception class raised by the dll.
The recommended aproach is to capture any exception within the Dll and create functions that return values of success or failure, then the host application can evaluate such results and raise an exception.
This is an example produces different results when compiled with Delphi or FreePascal, you shouldn't do this:
The correct method is this:
The recommended aproach is to capture any exception within the Dll and create functions that return values of success or failure, then the host application can evaluate such results and raise an exception.
This is an example produces different results when compiled with Delphi or FreePascal, you shouldn't do this:
library failedlib;
uses
SysUtils;
function divide(a, b: integer): Boolean; cdecl;
begin
if b = 0 then
raise Exception.Create('Can''t divide by zero');
Result := True;
end;
exports
divide;
end.
program sample;
{$APPTYPE CONSOLE}
type
TDivide = function (a, b: integer): Boolean; cdecl;
var
FuncDivide: TDivide;
lHandle: Cardinal;
begin
lHandle := LoadLibrary('failedlib.dll');
if lHanlde <> 0 then
begin
FuncDivide = GetProcAddress(lHandle, 'divide');
if pointer(@FuncDivide) <> nil then
begin
try
if FuncDivide(10, 0) then
writeln('Success!');
except
writeln('Failure!');
end;
end;
UnloadLibrary(lHandle);
end;
end.
The correct method is this:
library correctlib;
uses
SysUtils;
function divide(a, b: integer): Boolean; cdecl;
var
c: Integer;
begin
(* Catch any exception before return *)
try
c := a div b;
Result := True;
except
Result := False;
end;
end;
exports
divide;
end.
program sample;
{$APPTYPE CONSOLE}
type
TDivide = function (a, b: integer): Boolean; cdecl;
var
FuncDivide: TDivide;
lHandle: Cardinal;
begin
lHandle := LoadLibrary('correctlib.dll');
if lHanlde <> 0 then
begin
FuncDivide = GetProcAddress(lHandle, 'divide');
if pointer(@FuncDivide) <> nil then
begin
if FuncDivide(10, 0) then
writeln('Success!')
else
(* The exception is raised in the host app, not in the DLL *)
raise 'Failure!';
end;
UnloadLibrary(lHandle);
end;
end.
No comments:
Post a Comment