пятница, 12 апреля 2013 г.

Библиотеки и пакеты

Перевод раздела Libraries and Packages (Delphi) из справочной системы Delphi

Динамически загружаемые библиотеки – это библиотеки динамического связывания (dynamic-link library (DLL)) под Windows или DYLIB на Mac. Они представляют собой подборку подпрограмм, которые могут вызываться приложениями или другими библиотеками. Как и модули, динамически загружаемые библиотеки содержат программный код или ресурсы, предназначенные для совместного использования. Однако этот тип библиотеки компилируется отдельно и связывается с использующей его программой во время ее выполнения.

Программы, написанные на Delphi, могут вызывать DLL и сборки, написанные на других языках, и приложения, написанные на других языках, могут вызывать DLL или сборки, разработанные в Delphi.


Вызов динамически загружаемых библиотек

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

Прежде чем вы сможете вызывать подпрограммы, объявленные в DLL или сборке, вы должны импортировать их. Это может быть сделано двумя способами: путем объявления процедуры или функции с указанием директивы external или при помощи прямого обращения к операционной системе. Какой бы способ вы не использовали, подпрограммы не линкуются в приложение до его запуска.

Delphi не поддерживает импорт переменных из DLL или сборок.

Статическая загрузка

Простейший пример импорта процедуры или функции – это объявление ее с директивой external. Например:

procedure DoSomething; external 'MYLIB.DLL';

При включении такого объявления в программу, MYLIB.DLL загружается при запуске программы. Во время выполнения программы, идентификатор DoSomething ссылается на одну и ту же точку входа в библиотеке.

Объявления импортированных подпрограмм могут располагаться непосредственно в программе или модулях, откуда они вызываются. Для простоты вы можете собрать такие объявления в отдельный "модуль импорта", который также будет содержать константы и типы, необходимые для взаимодействия с библиотекой. Прочие модули, которые подключаются к модулю импорта, смогут вызывать все объявленные в нем подпрограммы.

Отложенная загрузка

Директиву delayed можно использовать для оформления отсрочки загрузки библиотеки, содержащей подпрограмму. Загрузка начинается только в момент первого обращения. Следующий пример показывает использование директивы delayed:

function GetSomething: Integer; external 'somelibrary.dll' delayed;

В этом примере подпрограмма GetSomething импортируется из библиотеки somelibrary.dll. Директива отложенной загрузки гарантирует, что библиотека somelibrary.dll линкуется в приложение динамически, а не статически.

Директива delayed будет полезна в случае, когда импортируемые подпрограммы могут не существовать в целевой операционной системе, где запускается приложение. Статически импортируемые подпрограммы требуют, чтобы операционная система нашла и загрузила библиотеку при запуске подпрограммы. Если подпрограмма не нашлась в загруженной библиотеке, или библиотека не существует, операционная система аварийно завершает приложение. Использование директивы delayed дает вам возможность при запуске программы проверить, поддерживает ли операционная система затребованные API, и только после этого вызывать импортируемые подпрограммы.

Еще одно возможное применение директивы delayed связано со следом приложения в памяти: оформление объявления редко используемых подпрограмм с указанием этой директивы может уменьшить след приложения в памяти, поскольку библиотеки загружаются только по требованию. Неверное использование директивы delayed может сказаться на производительности приложения и, в конечном счете, на пользователе.

Замечание: Попытка вызова несуществующей подпрограммы, объявленной с директивой delayed, приводит к возникновению ошибки выполнения приложения или к исключительной ситуации (если подключен модуль SysUtils).

Для настройки процесса отложенного вызова подпрограмм, подключаемого в Delphi Run-time Library, вы можете регистрировать процедуры-хуки, контролирующие и изменяющие его поведение. Чтобы сделать это, используйте SetDliNotifyHook2 и SetDliFailureHook2, объявленные в модуле SysInit.

Динамическая загрузка (только для Windows)

Вы можете получить доступ к библиотеке при прямом обращении к Windows API при помощи LoadLibrary, FreeLibrary иGetProcAddress. Эти функции объявлены в модуле Windows.pas. В этом случае следует пользоваться процедурными переменными для обращения к импортированным подпрограммам. Например:

 uses 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. Такой способ позволит вам сберечь память и запускать программу, даже когда некоторые используемые ею библиотеки отсутствуют.


Комментариев нет:

Отправить комментарий