Delphi: DLL библиотеки

КОМПЬЮТЕРНЫЕ КУРСЫ "ПОИСК"

[Главная страница] [Delphi] [Контакты]

Динамические подключаемые библиотеки


Создание библиотеки DLL

Чтобы создать новую библиотеку DLL в Delphi, выберите команду меню File > New > Other. В панели Items Categories окна New Items выберите узел Delphi Projects, после чего дважды щелкните на элементе Dynamic-link Library в правой панели окна.

Мастер DLL Wizard создает главный файл исходного кода библиотеки DLL, который выглядит практически так же, как и исходный код, сгенерированный для обычного приложения. Единственное отличие состоит в том. что этот файл начинается с зарезервированного слова library, а не program.

library Project1;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

{ Важное замечание относительно управления памятью библиотеки DLL: модуль
  ShareMem должен быть первым модулем в операторе uses вашей библиотеки
  и в операторе uses вашего проекта (выберите команду меню
  Project -> View Source (Проект -> Показать исходный код)), если ваша
  библиотека DLL экспортирует какие-либо процедуры или функции, передающие
  строки в качестве параметров или результатов выполнения функций. Это
  относится ко всем строкам, передаваемым или получаемым из вашей библиотеки
  DLL, и даже к тем строкам, которые вложены в записи и классы. Модуль
  ShareMem является модулем интерфейса для администратора общей памяти
  BORLNDMM.DLL, который вы должны развертывать вместе со своей библиотекой
  DLL. Чтобы не использовать BORLNDMM.DLL, передавайте строковую информацию
  с помощью параметров PChar или ShortString. }

uses
  SysUtils,
  Classes;

{$R *.res}

begin
end.

Все, что вам нужно сделать сейчас — это добавить подпрограмму перед блоком begin-end, вот и все. После этого вы получите внутреннюю подпрограмму, которую можно будет использовать в библиотеке DLL, но не во внешних приложениях. Если вы хотите вызывать подпрограмму из других приложении и других библиотек DLL, ее потребуетсл экспортировать. Чтобы экспортировать подпрограмму по имени, добавьте ее в список exports. Список exports имеет такой же синтаксис, что и список uses, за исключением того, что в списке exports любой элемент является подпрограммой, а не модулем.

Список exports обычно ставится непосредственно перед блоком begin-end. Взгляните на листинг 1, в котором представлен исходный код простой библиотеки FirstLib.dll, экспортирующей одну функцию.

Листинг 1. Простая библиотека DLL


library FirstLib;

function Max3(Num1, Num2, Num3: Integer): Integer; stdcall;
begin
  Result := Num1;
  if Num2 > Result then Result := Num2;
  if Num3 > Result then Result := Num3;
end;

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

begin
end.

Когда вы добавите подпрограмму в список exports, вы тем самым экспортируете подпрограмму по ее имени. Вы можете также экспортировать подпрограмму под другим именем с помощью директивы name или посредством порядкового значения, используя директиву index. Однако применять директиву index не рекомендуется.

Ниже показан пример экспортирования директивы посредством порядкового значения или под другим именем:

exports
  Max3 name 'MyMax3Function', SaySomething index 1;

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

Статическая загрузка является самым простым из двух возможных способов загрузки библиотеки DLL. Статическую загрузку называют еще динамическим подключением во время загрузки (load-time dynamic linking), потому что используемые библиотеки DLL автоматически загружаются во время запуска приложения.

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

Когда вы импортируете подпрограммы из библиотеки DLL, вы должны помечать их директивой external, указывая вслед за ней имя библиотеки DLL, в которой содержится реализация подпрограммы. Далее показан пример импорта функции МахЗ из библиотеки FirstLib.dll:

function Max3(Num1, Num2, Num3: Integer): Integer; stdcall; external 'FirstLib.dll';

При желании можете даже переименовать подпрограмму во время ее импорта. Для этого необходимо объявить подпрограмму под другим именем, а в конце объявления указать первоначальное имя с помощью директивы name:

function Max(Num1, Num2, Num3: Integer): Integer; stdcall; external 'FirstLib.dll' name 'Max3';

Вы можете также импортировать функцию из библиотеки DLL. Для этого нужно создать модуль импорта и написать стандартный заголовок подпрограммы в разделе interface, а ее внешнюю реализацию — в разделе implementation этого модуля. В листинге 2 показан полный код модуль импорта библиотеки FirstLib.dll.

Листинг 2. Модуль импорта библиотеки FirstLib.dll.


unit FirstLibInf;

interface

function Max3(Num1, Num2, Num3: Integer): Integer; stdcall;

implementation

const
  FirstLib = 'FirstLib.dll';
  {Компилятору сообщается о том, что реализация функции Max3 находится в библиотеке FirstLib.dll}
  function Max3; external FirstLib;

end.

После того как вы создадите библиотеку DLL и ее модуль импорта, протестируйте библиотеку DLL, чтобы убедиться в том. что подпрограмма работает нормально. Поскольку запустить саму библиотеку DLL нельзя, нужно создать тестовое приложение,  которое будет обращаться к библиотеке DLL. Быстрее всего сделать это можно, если создать проектную группу, добавив новый проект в текущий проект. Для этого потребуется щелкнуть правой кнопкой мыши на элементе ProjectGroup1 в окне Project Manager (Диспетчер проекта) и выбрать в контекстном меню команду Add New Project, как показано на рис. 1.

Листинг 3. Проверка подпрограммы Max3, импортированной из библиотеки FirstLib.dll.


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, FirstLibInf, StdCtrls;

type
  TMainForm = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Max3Button: TButton;
    procedure Max3ButtonClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

procedure TMainForm.Max3ButtonClick(Sender: TObject);
var
  LargestNumber: Integer;
begin
  LargestNumber := Max3(StrToInt(Edit1.Text), StrToInt(Edit2.Text), StrToInt(Edit3.Text));
  MessageDlg(Format('Наибольшее число: %d.', [LargestNumber]), mtInformation, [mbOK], 0);
end;

end.

Исходный код проекта (Delphi XE)

Используемая литература: Внутренний мир Borland Delphi 2006. Иван Хладни.