Originale-mail to me for new edition

 

Writing dynamically loadable libraries

 

The main source for a dynamically loadable library is identical to that of a program, except that it begins with the reserved word library (instead of program).

Only routines that a library explicitly exports are available for importing by other libraries or programs. The following example shows a library with two exported functions, Min and Max.

library MinMax;

function Min(X, Y: Integer): Integer; stdcall;

begin

  if X < Y then Min := X else Min := Y;

end;

function Max(X, Y: Integer): Integer; stdcall;

begin

  if X > Y then Max := X else Max := Y;

end;

exports

  Min,

  Max;

begin

end.

If you want your library to be available to applications written in other languages, it’s safest to specify stdcall in the declarations of exported functions. Other languages may not support Object Pascal’s default register calling convention.

Libraries can be built from multiple units. In this case, the library source file is frequently reduced to a uses clause, an exports clause, and the initialization code. For example,

library Editors;

uses EdInit, EdInOut, EdFormat, EdPrint;

exports

  InitEditors,

  DoneEditors name Done,

  InsertText name Insert,

  DeleteSelection name Delete,

  FormatSelection,

  PrintSelection name Print,

   ...

  SetErrorHandler;

begin

  InitLibrary;

end.

You can put exports clauses in the interface or implementation section of a unit. Any library that includes such a unit in its uses clause automatically exports the routines listed the unit’s exports clauses without the need for an exports clause of its own.

The directive local, which marks routines as unavailable for export, is platform-specific and has no effect in Windows programming.

On Linux, the local directive provides a slight performance optimization for routines that are compiled into a library but are not exported. This directive can be specified for standalone procedures and functions, but not for methods. A routine declared with local, for example,

function Contraband(I: Integer): Integer; local;

does not refresh the EBX register and hence

·   cannot be exported from a library.

·   cannot be declared in the interface section of a unit.

·   cannot have its address taken or be assigned to a procedural-type variable.

·   if it is a pure assembler routine, cannot be called from another unit unless the caller sets up EBX.

 

The exports clause

Library initialization code

Global variables in a library

Libraries and system variables

Exceptions and runtime errors in libraries

The shared-memory manager (Windows only)

 

Topic groups

 

See also

Calling conventions

Calling dynamically loadable libraries

External declarations

Libraries and packages: Overview

Program structure and syntax: Overview

 

 

译文

 

编写动态可加载库

 

动态可加载库的主源代码与程序的主源代码是一样的,除了前者以保留字library开始而后者以保留字program开始之外。

只有在库中被明确输出的例程可以被其他库或程序引入。下面是一个库的例子,该库有两个输出的函数,MinMax

library MinMax;

function Min(X, Y: Integer): Integer; stdcall;

begin

  if X < Y then Min := X else Min := Y;

end;

function Max(X, Y: Integer): Integer; stdcall;

begin

  if X > Y then Max := X else Max := Y;

end;

exports

  Min,

  Max;

begin

end.

如果想要让库对由其他语言编写的由于程序是可用的,那么在输出函数的声明中指定stdcall调用约定是最可靠的。其他语言可能不支持Object Pascal中缺省的register调用约定。

库可以由多个单元建立。此时,库的源文件通常缩减为一个uses子句,一个exports子句,以及初始化代码。例如,

library Editors;

uses EdInit, EdInOut, EdFormat, EdPrint;

exports

  InitEditors,

  DoneEditors name Done,

  InsertText name Insert,

  DeleteSelection name Delete,

  FormatSelection,

  PrintSelection name Print,

   ...

  SetErrorHandler;

begin

  InitLibrary;

end.

exports子句可以位于单元的接口节(interface)或实现节(implementation)。对于任何库,只要在其uses子句中包含了这样的单元,那么库会自动输出列于这些单元内exports子句中的所有例程,而不需要在库的exports子句中再次输出。

指示字local用于标明例程是不可被输出的,该指示字因具体平台的不同而具有不同的意义,它对Windows编程中没有影响。

Linux中,local指示字对编译到库中但不被输出的例程提供一些性能优化。该指示字可以被指定到单独的过程和函数,但不能指定到方法。下面是用指示字local声明例程的例子,

function Contraband(I: Integer): Integer; local;

由于该例程不能更新EBX寄存器,因此

·   不能从库中被输出

·   不能声明在单元的接口节(interface

·   不能拥有自身的地址处理或被赋值到程序型变量。

·   如果例程是一个纯粹的汇编例程,那么它不能被其他单元调用,除非调用者设置了EBX寄存器。

 

exports子句

库的初始化代码

库中的全局变量

库和系统变量

库中的异常和运行时错误

共享内存管理(仅适用于Windows

 

主题组

 

相关主题

调用约定

调用动态可加载库

外部声明

库和包:概述

程序结构和语法:概述