Calling Dynamically Loadable Libraries
You can call operating system routines directly, but they are not linked to your application until runtime. This means
that the library need not be present when you compile your program. It also means that there is no compile-time
validation of attempts to import a routine.
Before you can call routines defined in DLL or assembly, you must import them. This can be done in two ways: by
declaring an external procedure or function, or by direct calls to the operating system. Whichever method you use,
the routines are not linked to your application until runtime.
The Delphi language does not support importing of variables from DLLs or assemblies.
Static Loading
The simplest way to import a procedure or function is to declare it using the external directive. For example,
procedure DoSomething; external 'MYLIB.DLL';
If you include this declaration in a program, MYLIB.DLL is loaded once, when the program starts. Throughout
execution of the program, the identifier
DoSomething
always refers to the same entry point in the same shared
library.
Declarations of imported routines can be placed directly in the program or unit where they are called. To simplify
maintenance, however, you can collect external declarations into a separate "import unit" that also contains any
constants and types required for interfacing with the library. Other modules that use the import unit can call any
routines declared in it.
Dynamic Loading
You can access routines in a library through direct calls to Win32 APIs, including
LoadLibrary
,
FreeLibrary
,
and
GetProcAddress
. These functions are declared in Windows.pas. on Linux, they are implemented for
compatibility in SysUtils.pas; the actual Linux OS routines are dlopen, dlclose, and dlsym (all declared in libc; see
the man pages for more information). In this case, use procedural-type variables to reference the imported routines.
For example,
uses Windows, ...;
type
TTimeRec = record
Second: Integer;
Minute: Integer;
Hour: Integer;
end;
179
TGetTime = procedure(var Time: TTimeRec);
THandle = Integer;
var
Time: TTimeRec;
Handle: THandle;
GetTime: TGetTime;
.
.
.
begin
Handle := LoadLibrary('libraryname');
if Handle <> 0 then
begin
@GetTime := GetProcAddress(Handle, 'GetTime');
if @GetTime <> nil then
begin
GetTime(Time);
with Time do
WriteLn('The time is ', Hour, ':', Minute, ':', Second);
end;
FreeLibrary(Handle);
end;
end;
When you import routines this way, the library is not loaded until the code containing the call to
LoadLibrary
executes. The library is later unloaded by the call to
FreeLibrary
. This allows you to conserve memory and to run
your program even when some of the libraries it uses are not present.
180
|