| Delphi Clinic | C++Builder Gate | Training & Consultancy | Delphi Notes Weblog | Dr.Bob's Webshop |
| ||||||
Delphi XE2 64-bit DLLs
Delphi XE2 can produce 64-bit Windows applications and DLLs.
In the 64-bit Windows world, DLLs have only a single calling convention, and we do not have to specify that in Delphi.
However, if we do specify a calling convention, it will be ignored by the 64-bit compiler (and used by the 32-bit compiled in case we compile for a 32-bit target), so it's still advised to use the calling conventions for backwards compatibility with the 32-bit world.
An example of a library (with calling convention specified) is as follows:
library MyMax;
uses
SysUtils, Classes;
function Max(X: array of Integer): Integer; stdcall; export;
var
NextX: Integer;
begin
Result := 0;
if Length(X) > 0 then
begin
Result := X[0];
for NextX in X do
if NextX > Result then Result := NextX
end
end;
exports
Max;
begin
end.
The implicit import of this 64-bit DLL can be as follows:
function Max(X: array of Integer): Integer; stdcall; external 'MyMax.dll';And the call is as follows:
a := Max([2,10,42]);Note that not all development environments will be able to call the function with the array of integers as argument type. Another example of a DLL for both 32-bit and 64-bit is as follows:
library eBob42;
function Add(X,Y: Integer): Integer; overload; stdcall;
begin
Result := X + Y
end;
function Add(X,Y: Double): Double; overload; stdcall;
begin
Result := X + Y
end;
exports
Add(X,Y: Integer) name 'Add',
Add(X,Y: Double) name 'AddDouble';
end.
This example was taken from the Delphi XE Development Essentials (the free bonus PDF for developers who purchased my courseware manuals).
As explained in the XE courseware manual, apart from implicit loading the DLL, we can also write some more code and do an explicit load.
The advantage of an explicit load is that the application will continue to run even if the DLL is not available (which in note the case with an implicit import: in that situation, the application will not start if the implicitly imported DLL cannot be found or loaded).
XE2 Delay Loading DLLs
Delphi 2010 introduced the delayed keyword (no syntax highlighting by the way), and I wrote about a feature to hook into the delay failure notifier using the SetDliFailureHook in Delphi 2010, which still works in Delphi XE.
For Delphi XE2, the SetDliFailureHook is gone, and replaced by SetDliFailureHook2. As a result my DelayedHandler unit, for responding to errors when trying to load a DLL or trying to call a method from the DLL, is now implemented as follows:
unit DelayedHandler;
interface
uses
SysUtils;
type
ELoadLibrary = class(Exception);
EGetProcAddress = class(Exception);
implementation
function DelayedHandlerHook(dliNotify: dliNotification;
pdli: PDelayLoadInfo): Pointer; stdcall;
begin
Result := nil; // to get rid of warning W1035
if dliNotify = dliFailLoadLibrary then
raise ELoadLibrary.Create('Could not load ' + pdli.szDll)
else
if dliNotify = dliFailGetProcAddress then
begin
if pdli.dlp.fImportByName then
raise EGetProcAddress.Create('Could not load ' +
pdli.dlp.szProcName + ' from ' + pdli.szDll)
else
raise EGetProcAddress.Create('Could not load index ' +
IntToStr(pdli.dlp.dwOrdinal) + ' from ' + pdli.szDll)
end
end;
initialization
{$IFDEF VER220}
SetDliFailureHook(DelayedHandlerHook); // XE
{$ENDIF}
{$IFDEF VER230}
SetDliFailureHook2(DelayedHandlerHook); // XE2
{$ENDIF}
finalization
{$IFDEF VER220}
SetDliFailureHook(nil); // XE
{$ENDIF}
{$IFDEF VER230}
SetDliFailureHook2(nil); // XE2
{$ENDIF}
end.
Feel free to add VER210 support for Delphi 2010 if you still use that version of Delphi.
Note that we may have to modify this code when Delphi XE3 is released (but that will be covered in my Delphi XE3 Development Essentials courseware manual, of course).
unit eBob42Delayed;
interface
const
DLL = 'eBob42.DLL';
function Add(X,Y: Integer): Integer; overload; stdcall
external DLL delayed;
function Add(X,Y: Double): Double; overload; stdcall
external DLL name 'AddDouble' delayed;
implementation
end.
Summary