Главная » Delphi » Создание и использование библиотек DLL

0

В этом  разделе демонстрируется процесс создания реальной библиотеки DLL  в среде  Delphi. Рассмотрим, как  создается модуль  интерфейса, позволяющий сделать библиотеку DLL доступной другим программам. Но прежде чем перейти к более сложным вопросам использования библиотек в Delphi, давайте  познакомимся с мето дами размещения в библиотеке DLL форм  Delphi.

Подсчет пенсов (пример простой  DLL)

В данном  примере проиллюстрировано размещение в библиотеке DLL функции, которую   очень   любят   предлагать студентам   профессора  компьютерных наук.  Эта функция рассчитывает минимальное количество монет  достоинством в 1 пенс,  5 пен сов (nickel), 10 пенсов  (dime) и 25 пенсов  (quarter), чтобы  получить заданную сумму.

Простейшая  DLL

Создаваемая библиотека содержит метод PenniesToCoins(). В листинге 6.1 при

веден законченный проект библиотеки DLL.

Листинг 6.1. PenniesLib.dpr — DLL для пересчета пенсов в другие монеты

library PenniesLib;

{$DEFINE PENNIESLIB}

uses

SysUtils, Classes, PenniesInt;

function PenniesToCoins(TotPennies: word;

CoinsRec: PCoinsRec): word; StdCall;

begin

Result := TotPennies;      // Присвоение значения Result

{ Вычисление количества монет по 25, 10, 5, и 1 пенсу }

with CoinsRec^ do begin

Quarters          := TotPennies div 25;

TotPennies := TotPennies – Quarters * 25;

Dimes             := TotPennies div 10;

TotPennies := TotPennies – Dimes * 10;

Nickels           := TotPennies div 5;

TotPennies := TotPennies – Nickels * 5;

Pennies           := TotPennies;

end;

end;

{ Экспорт функции по имени }exports

PenniesToCoins;

end.Обратите внимание, что в этой библиотеке используется модуль PenniesInt, ко

торый более подробно рассматривается чуть ниже.

Раздел  exports указывает, какие  функции и процедуры данной библиотеки DLL

экспортируются и станут доступными вызывающим приложениям.

Определение модуля интерфейса

Модуль интерфейса позволяет пользователям созданной DLL статически импорти ровать функции данной библиотеки в свои приложения, разместив имя импортируемо го модуля в разделе uses. Модули интерфейса позволяют разработчику библиотеки DLL определять общие структуры, используемые как самой библиотекой, так и вызывающим приложением. Продемонстрируем эти возможности на примере модуля интерфейса для библиотеки PenniesLib.dll. В листинге 6.2 содержится исходный код раздела  inter- face модуля PenniesInt.pas.

Листинг 6.2. PenniesInt.pas — модуль интерфейса PenniesLib.dll

unit PenniesInt;

{ Процедуры интерфейса для PENNIES.DLL }

interface type

{ Эта запись будет содержать перечень монет после выполнения преобразований. }

PCoinsRec = ^TCoinsRec; TCoinsRec = record

Quarters, Dimes, Nickels,

Pennies: word;

end;

{$IFNDEF PENNIESLIB}

{ Объявление функции с использованием ключевого слова export }

function PenniesToCoins(TotPennies: word;

CoinsRec: PCoinsRec): word; StdCall;

{$ENDIF}

implementation

{$IFNDEF PENNIESLIB}

{ Определение импортируемой функции }

function PenniesToCoins;

external ‘PENNIESLIB.DLL’ name ‘PenniesToCoins';

{$ENDIF}

end.В разделе type этого  проекта объявлена запись  TCoinsRec, а также  указатель  на нее. Такая запись  будет содержать сведения о количестве монет  каждого  достоинства, необходимых для вычисления суммы в пенсах, переданной функции PenniesToCo- ins(). Этой  функции передается два параметра: общая  сумма денег в пенсах  и указа тель на переменную TCoinsRec. Результатом выполнения функции является та же самая денежная сумма, которая была ей передана в качестве параметра, но уже в виде некоторого набора монет.

В модуле PenniesInt.pas объявляется функция, которую  библиотека Pennies- Lib.dll экспортирует в своем разделе interface. Определение функции находится в разделе implementation (реализации). Это  определение означает, что  функция является внешней и расположена в файле DLL PenniesLib.dll. Связь  с функцией DLL устанавливается по имени функции. Обратите внимание, что здесь была исполь зована   директива $IFNDEF PENNIESLIB, применяемая для  выполнения  условной компиляции объявления функции PenniesToCoins(). Это сделано  потому,  что  нет необходимости компоновать данное  объявление при компиляции модуля интерфейса библиотеки. Указанное позволяет совместно использовать объявления типа из модуля интерфейса как другим  библиотекам, так  и любым  другим  приложениями, которые будут использовать эту библиотеку. Любые  изменения в структуру,  используемую  как библиотекой, так и приложениями, нужно вносить только  в модуле интерфейса.

CОВЕТ

Чтобы определить директиву условной компиляции в масштабе приложения, укажите ее во вкладке Directories/Conditionals диалогового окна Options проекта. После этого следует обязательно заново создать данный проект, чтобы вступили в силу измене- ния, связанные с условными директивами, поскольку в логике команды Make не преду- смотрено переоценки условных определений.

НА ЗАМЕТКУ

Следующее определение показывает один из двух возможных способов импорта функции DLL:

function PenniesToCoins; external ‘PENNIESLIB.DLL’ index 1;

Этот метод называется импортом по порядковому номеру (importing by ordinal). Им- портировать функции DLL можно также и другим способом, который имеет название импорт по имени (importing by name):

function PenniesToCoins; external ‘PENNIESLIB.DLL’ name ‘PenniesToCoins';

Нетрудно догадаться, что метод определения связываемой функции по имени исполь-

зует ее имя, указанное после ключевого слова name.

При использовании импорта по порядковому номеру уменьшается время загрузки биб-

лиотеки DLL, поскольку в этом случае отпадает необходимость поиска имени функции в таблице имен. Тем не менее, в Win32 предпочтение отдается импорту по

имени. В таком случае приложению удается избежать нежелательной жесткой привязки к конкретному месторасположению точек входа в функции DLL, которое может изменитьсяпри обновлении библиотеки. При импорте по порядковому номеру программа привязана к определенному месту в библиотеке DLL, а при импорте по имени — к имени функции, независимо от ее расположения в библиотеке.

Если рассматриваемая выше библиотека была бы реальной DLL, которую  предпо лагалось  использовать и в дальнейшем, то следовало бы предоставить пользователям оба файла  — и PenniesLib.dll, и PenniesInt.pas. Тогда  они  смогли  бы работать с данной библиотекой, определяя в модуле PenniesInt.pas типы  и функции, необхо димые  для PenniesLib.dll. Кроме  того,  программисты, работающие на других язы ках (например C++), могли  бы преобразовать модуль PenniesInt.pas в формат сво его языка, что  позволило бы им использовать данную библиотеку DLL в своей  среде разработки. Проект, работающий с библиотекой PenniesLib.dll, можно  найти на прилагаемом компакт диске (см. также www.williamspublishing.com).

Источник: Тейксейра, Стив, Пачеко, Ксавье.   Borland Delphi 6. Руководство разработчика. : Пер.  с англ. — М. : Издательский дом “Вильямс”, 2002. —  1120 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии