Originale-mail to me for new edition

 

Dynamic loading

 

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.

 

Topic groups

 

See also

Calling dynamically loadable libraries

Procedural types in statements and expressions

Procedural types: Overview

 

 

译文

 

动态加载

 

可以通过对操作系统(OS)中库函数的直接调用来实现对库中例程的访问,操作系统库函数包括LoadLibraryFreeLibraryGetProcAddress。在Windows中,这三个函数声明在Windows.pas中;在Linux中,为了跨平台兼容,它们在SysUtils.pas中被实现;实际的Linux操作系统例程是dlopendlclosedlsym(所有的声明在KylixLibc单元中;更多的相关信息见man页)。这时,可以使用程序型类型的变量来引用引入的例程。

例如,在WindowsLinux中,

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被卸载。这样也可以减少内存开销。

 

主题组

 

相关主题

调用动态可加载库

语句和表达式中的程序型类型

程序型类型:概述