12.3. Использование библиотеки в программе на Pascal

Вверх  Предыдущий  Следующий

Чтобы использовать функцию из библиотеки, достаточно объявить, что эта функция в библиотеке существует как внешняя (external), с правильными аргументами и типом возвращаемого значения. Используемое функцией соглашение о вызовах должно быть также правильно объявлено. Затем компилятор скомпонует библиотеку, как это указано в операторе external для вашей программы (если вы опустите имя библиотеки в модификаторе external, то вы всё равно можете указать компилятору ссылку на эту библиотеку, используя директиву {$Linklib}).

Например, для использования описанной выше библиотеки из программы на Pascal, вы можете использовать следующий способ:

Листинг: progex/psubs.pp

program testsubs;
function SubStr(const CString : PChar; FromPos, ToPos : longint) : PChar;
            cdecl; external 'subs';
var
  s : PChar;
  FromPos, ToPos : Integer;
 
begin
  s : = 'Test';
  FromPos : = 2;
  ToPos : = 3;
  WriteLn(SubStr(s, FromPos, ToPos));
end.

Как показано в примере, вы должны объявить функцию как внешнюю (external). Здесь также необходимо определить правильное соглашение о вызовах (оно должно всегда соответствовать соглашению, используемому функцией в библиотеке) и использовать правильный формат вашего объявления. Также обратите внимание, что в имени импортируемой библиотеки не указывается расширение, и префикс lib также не добавляется.

Эта программа может быть откомпилирована без каких-либо дополнительных командных переключателей, и должна выполняться только в том случае, если предоставленная библиотека размещена в таком месте, где система может её найти. Например, для LINUX это /usr/lib или любая из директорий, перечисленных в файле /etc/ld.so.conf. Для WINDOWS это может быть каталог программы или любой каталог, упомянутый в команде PATH.

При подобном методе связи библиотеки с вашей программой библиотека используется во время компиляции. Это означает, что

1.Библиотека должна быть представлена в системе, где программа компилируется.

2.Библиотека должна быть представлена в системе, где программа выполняется.

3.Обе библиотеки должны быть одинаковыми.

А ещё может быть, что вы не знаете имя вызываемой функции, вы только знаете аргументы, которые она принимает.

Поэтому также возможно загрузить библиотеку во время выполнения, записать адрес функции в процедурную переменную и использовать эту процедурную переменную для доступа к функции в библиотеке.

Следующий пример демонстрирует эту технологию:

Листинг: progex/plsubs.pp

program testsubs;
 
Type
  TSubStrFunc =
    function(const CString : PChar; FromPos, ToPos : longint) : PChar; cdecl;
 
Function dlopen(name : pchar; mode : longint) : pointer; cdecl; external 'd l';
Function dlsym(lib : pointer; name : pchar) : pointer; cdecl; external 'dl';
Function dlclose(lib : pointer) : longint; cdecl; external 'dl';
 
Var
S : PChar;
FromPos, ToPos : Integer;
lib : pointer;
SubStr : TSubStrFunc;
 
begin
  s : = 'Test';
  FromPos : = 2;
  ToPos : = 3;
  lib := dlopen('libsubs.so', 1);
  Pointer(Substr) : = dlsym(lib, 'SubStr');
  WriteLn(SubStr(s, FromPos, ToPos));
  dlclose(lib);
end.

Как и в случае связи во время компиляции, главное в этом листинге – это объявление типа TSubStrFunc. Он должен соответствовать объявлению функции, которую вы пытаетесь использовать. Неправильное объявление приведёт к повреждению стека или, что ещё хуже, ваша программа может вызвать крах системы.