You can
access routines in a library through direct calls to OS library functions,
including LoadLibrary, FreeLibrary, and GetProcAddress. In
Windows, 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 Kylix’s Libc
unit; see the man pages for more information). In this case, use
procedural-type variables to reference the imported routines.
For
example, on Windows or Linux:
uses
Windows, ...; {On Linux, replace Windows with SysUtils }
type
TTimeRec = record
Second: Integer;
Minute: Integer;
Hour: Integer;
end;
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.
This same
example can also be written on Linux as follows:
uses
Libc, ...;
type
TTimeRec = record
Second: Integer;
Minute: Integer;
Hour: Integer;
end;
TGetTime = procedure(var
Time: TTimeRec);
THandle = Pointer;
var
Time: TTimeRec;
Handle: THandle;
GetTime: TGetTime;
...
begin
Handle := dlopen('datetime.so',
RTLD_LAZY);
if Handle <> 0 then
begin
@GetTime := dlsym(Handle,
'GetTime');
if @GetTime <>
nil then
begin
GetTime(Time);
with
Time do
WriteLn('The time is ', Hour, ':', Minute, ':', Second);
end;
dlclose(Handle);
end;
end;
In this case, when importing routines, the shared object is not loaded until the code containing the call to dlopen executes. The shared object is later unloaded by the call to dlclose. This also allows you to conserve memory and to run your program even when some of the shared objects it uses are not present.
Calling dynamically
loadable libraries
Procedural
types in statements and expressions
可以通过对操作系统(OS)中库函数的直接调用来实现对库中例程的访问,操作系统库函数包括LoadLibrary、FreeLibrary和GetProcAddress。在Windows中,这三个函数声明在Windows.pas中;在Linux中,为了跨平台兼容,它们在SysUtils.pas中被实现;实际的Linux操作系统例程是dlopen、dlclose和dlsym(所有的声明在Kylix的Libc单元中;更多的相关信息见man页)。这时,可以使用程序型类型的变量来引用引入的例程。
例如,在Windows或Linux中,
uses
Windows, ...; { 对于Linux,应用SysUtils代替Windows
}
type
TTimeRec = record
Second: Integer;
Minute: Integer;
Hour: Integer;
end;
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;
通过这种方法引入例程使,库直到含有调用LoadLibrary的代码执行时才被加载。该库后来通过调用FreeLibrary被卸载。当程序使用的库不必在内存中继续存在时,这种动态加载的方式就可以保持内存和运行程序。
相同的例子在Linux中还可以如下编写:
uses
Libc, ...;
type
TTimeRec = record
Second: Integer;
Minute: Integer;
Hour: Integer;
end;
TGetTime = procedure(var
Time: TTimeRec);
THandle = Pointer;
var
Time: TTimeRec;
Handle: THandle;
GetTime: TGetTime;
...
begin
Handle := dlopen('datetime.so',
RTLD_LAZY);
if Handle <> 0 then
begin
@GetTime := dlsym(Handle,
'GetTime');
if @GetTime <>
nil then
begin
GetTime(Time);
with
Time do
WriteLn('The time is ', Hour, ':', Minute, ':', Second);
end;
dlclose(Handle);
end;
end;
在这种情况下,引入例程时,共享对象直到含有调用dlopen的代码执行时才被加载。共享对象后来通过调用dlcose被卸载。这样也可以减少内存开销。