Cоздание библиотеки в delphi. Загрузка DLL в delphi приложении. способ. Привязка DLL к программе

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

Для того чтобы создать DLL-библиотеку, для начало необходимо выполнить команду меню File|New|Other и выбрать на странице New диалога New Item элемент DLL Wizard.

Мастер DLL Wizard автоматически создаст пустой шаблон для DLL-библиотеки. В отличие от обычного модуля, начинающегося с ключевого слова unit, модуль DLL-библиотеки начинается с ключевого слова library. Секция uses модуля DLL-библиотеки требует подключения только двух пакетов: SysUtils и Classes.

Создание DLL-функции состоит из нескольких этапов:

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

3. В заключение функцию, которую предполагается использовать не только внутри модуля, но и вызывать из других приложений, следует объявить как экспортируемую в секции exports.

Функции из DLL-библиотеки могут вызываться как из приложений, разработанных в Delphi, так и из приложений, написанных на других языках программирования, таких, как C++.

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

Способ передачи параметров указывается через точку с запятой после описания функции. Например:

function F1 (X, Y, Z: Real]: Real; stdcall;.

Различные способы передачи параметров определяют порядок передачи параметров (слева направо или справа налево), а также указывают, кто будет освобождать память стека (вызываемая или вызывающая процедура). При использовании DLL-библиотек в качестве компонентов, вызываемых из приложений на других языках программирования, следует использовать соответствующий модификатор вызова. Для приложений на C++ применяется модификатор вызова stdcall.

Для того чтобы функцию, описанную в DLL-библиотеке, можно было вызвать из другого приложения, эту функцию следует экспортировать. Список всех экспортируемых функций указывается в секции exports через запятую

и завершается символом точка с запятой. Экспорт функций может выполняться тремя способами:

По имени функции, используемому в DLL-библиотеке;

По имени функции, заданному как имя экспорта;

По присвоенному функции индексу.

Для того чтобы присвоить функции некоторый индекс, его следует указать в секции exports после имени функции с ключевым словом index.

Для того чтобы экспортируемая функция вызывалась по имени, отличном от имени, используемого в DLL-библиотеке, в секции exports после имени функции следует указать ключевое слово name и новое имя экспорта для данной функции.

DLL - библиотека не является выполняемым модулем. Для получения ее кода достаточно произвести компиляцию проекта.

library Projectl;

SysUtils, Classes;

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

Статическое подключение DLL-библиотеки

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

При статическом подключении DLL-библиотека загружается один раз при запуске приложения. На всем протяжении выполнения приложения имя функции, импортируемой из DLL-библиотеки, которая была подключена статически, указывает на одну и ту же функцию (точку входа в DLL) в одной и той же DLL. Все функции из DLL-библиотеки, которые будут использоваться в приложении первоначально, должны быть объявлены как внешние. При этом следует указать, если требуется, модификатор вызова. Если функция вызывается по индексу, то для нее следует задать имя, используемое в приложении, и индекс функции в DLL-библиотеке.

Объявления внешних функций выполняется в секции implementation до использования этих функций.

Объявление внешней функции с ключевым словом external определяет, что будет использовано статическое связывание.

TForml = class(TForm)

Editl: TEdit; [Поле для ввода первого значения}

Edit2: TEdit; (Поле для ввода второго значения}

Edit3: TEdit; (Поле для отображения результата

выполнения функции из DLL-библиотеки}

Buttonl: TButton; {Выполняется вызов функции, используемой по имени)

Button2: TButton; [Выполняется вызов функции, используемой по индексу}

procedure ButtonlClickfSender: TObject);

procedure Button2Click(Sender: TObject);

{ Private declarations }

(Public declarations }

(Объявление экспортируемых функций}

function Fl (i: Integer; j:Integer): Integer; stdcall;

external "Projectl.dll";

function F2 (i: Integer; j:Integer): Integer; stdcall;

external "Projectl.dll index 2;

procedure TForml.ButtonlClick(Sender: TObject);

{Вызов экспортируемой функции}

Edit3.Text:=IntToStr(Fl(StrToInt(Editl.Text),StrToInt{Edit2.Text)));

procedure TForml.Button2Click(Sender: TObject);

Edit3.Text:=JntToStr(F2(StrToInt(Editl.Text),StrToInt(Edit2.Text)));

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

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

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

Для того чтобы выполнить вызов функции из динамически подключаемой DLL-библиотеки, выполните следующие действия:

1. Создайте новый тип. соответствующий типу вызываемой функции (имя нового типа можно ввести после секции type).

Например:

TMyFl=function(i,j:Integer):Integer; stdcall;

2. В секции var interface-секции модуля создайте переменную созданного типа функции. Например: MyFl: TMyFl;

3. Перед загрузкой DLL-библиотеки объявите переменную типа Integer, которая будет содержать дескриптор подключаемой библиотеки.

4. Вызовите метод LoadLibrary, выполняющий подключение DLL-библиотеки. Например; h:=LoadLibrary ("Projectl.dll");

5. Проверьте, успешно ли выполнено подключение библиотеки. Если имя DLL-библиотеки указано неверно или библиотека не найдена, то функция LoadLibrary вернет значение 0.

6. В случае успешного подключения DLL-библиотеки далее следует получить адрес функции. Для этого используется функция Windows API GetProcAddress, в качестве параметров которой указывается дескриптор DLL-библиотеки и имя подключаемой функции. Например: @MyFl: =GetProcAddress (h, " Fl ");

7. Если адрес функции получен, то значение адреса (в нашем примере @MyFl) не должно быть равно nil.

8. На этом этапе можно выполнять вызов функции из динамически подключенной DLL-библиотеки.

9. Для освобождения и соответственно выгрузки DLL-библиотеки вызовите метод FreeLibrary, выполняющий отключение DLL-библиотеки.

Windows, Messages, SysUtils, Variants, Classes, Graphics,

Controls, Forms, Dialogs, StdCtrls;

TForml = class(TForm)

Button3: TButton;

procedure Button3Click

procedure TForml.Button3Click(Sender: TObject);

h:=LoadLibrary("Projectl.dll");

if h <> 0 then

@MyFl:=GetProcAddress(h,"Fl");

if @MyFl <> nil then

Edit3.Text:=IntToStr(MyFl(StrToInt{Editl.Text),

StrToInt(Edit2.Text)));

Использование DLL-библиотеки для вызова общих модальных диалогов.

Результатом выполнения процедуры из DLL-библиотеки может быть отображение некоторого модального диалога. Для этого следует в экспортируемом методе создать объект форма, отобразить ее как модальный диалог, а затем удалить объект форма. При этом в самой форме следует предусмотреть вызов метода Close для завершения диалога.

Для создания формы используется метод Create, в качестве параметра которому передается указатель на родительскую форму - форму вызывающего приложения. Этот параметр передается вызываемой DLL-функции.

library Projectl;

Unitl_DLL in "Unitl_DLL.pas" {Forml};

procedure MyModalForm (var Z:Integer ;F:TForm1); stdcall;

Form1:=TForml.Create(F);

(Параметр F передается при вызове процедуры и содержит указатель

на родительскую форму - форму вызывающего приложения}

Что такое DLL - знает, как минимум, большинство пользователей PC, тем более программисты, к которым Вы, скорее всего и относитесь, раз читаете эту статью. В этой статье я постараюсь пробежаться по всем общим вопросам, касающимся DLL.

Что конкретно мы рассмотрим:

  1. Как обычно, из области "Hello World", мы создадим свою первую DLL.
  2. Научимся пользоваться функциями этой DLL из своих программ.
  3. Научимся просматривать функции, которые экспортирует определенная DLL.
  4. Может, что нибудь еще....

Процесс создания DLL

Начнем с самого простого - написание своей первой DLL, которая будет содержать всего лишь одну функцию, которая выводит сообщение "Hello World".

  1. Запускаем Delphi (Я использую Delphi 6).
  2. Далее: File -> New ->Other

На закладке New дважды щелкаем по объекту DLL Wizard. Откроется новый проект. Сохраните его, например, с именем MyFirstDLL.

Чистый модуль имеет примерно такое содержание:

Library MyFirstDLL; uses SysUtils, Classes; {$R *.res} begin end.

Теперь напишем всего лишь одну функцию, которая вызовет ShowMessage() из модуля Dialogs. Следовательно, перед началом оформления процедуры допишем в раздел Uses модуль Dialogs. Что, примерно, должно у вас получится:

Library MyFirstDLL; uses Dialogs; procedure MyFirstFunc; stdcall; begin ShowMessage("Hello World"); end; exports MyFirstFunc; begin end.

Как видите, тут нет ничего очень сложного. Единственное скажу, что можно вызывать функции как по имени, так и по индексу (номеру), для этого надо писать так:

Exports MyFirstFunc index 1;

Если что не понятно в этом коде, то все таки постарайтесь разобраться сначала сами. Думаю, что с этим проблем не будет... Но если что, то forum.! Идем дальше, как же можно теперь пользоваться этой (MyFirstFunc) функцией из других проектов?

Использование функций DLL

Первый шаг сделан, дело за малым... Как нам использовать эту функцию?

Есть, как минимум, два способа загрузки:

  1. Статический
  2. Динамический

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

Создаем новый проект, бросаем на форму одну кнопку и по событию OnClick этой кнопки и пишем следующее:

Procedure TForm1.Button1Click(Sender: TObject); begin MyProc(); end;

Но это еще не все! В разделе implementation проекта запишите:

Implementation procedure MyProc(); stdcall; external "MyFirstDLL.dll" name "MyFirstFunc";

Готово! Компилируйте проект и жмите на кнопку! Если показалось ваше сообщение, то все ок!

Теперь рассмотрим способ с динамической загрузкой. Для этого метода используют функцию LoadLibrary(), а в конце, для выгрузки - FreeLibrary().

Посмотрите на примере:

Procedure TForm1.Button1Click(Sender: TObject); type TMyFunc = procedure; var DLLInstance: THandle; MyFunc: TMyFunc; begin DLLInstance:= LoadLibrary(PChar("MyFirstDLL.dll")); if (DLLInstance = 0) then begin MessageDlg("Невозможно загрузить DLL", mtError, , 0); Exit; end; try @MyFunc:= GetProcAddress(DLLInstance, "MyFirstFunc"); if Assigned(@MyFunc) then MyFunc() else MessageDlg("Не найдена искомая процедура!.", mtError, , 0); finally FreeLibrary(DLLInstance); end; end;

После успешной загрузки DLL функцией LoadLibrary(), с помощью GetProcAddress() найдем адрес нашей функции, по которому и будем вызывать нашу процедуру из DLL. В конце, обязательно, надо сделать FreeLibrary(). Это настолько важно, что весь код после успешной загрузки, вполть до FreeLibrary() я заключил в блок try finally. Это гарантирует выполнение FreeLibrary, даже если при выполнении действий внутри блока try except, возникнет непредвиденная ошибка в виде исключения (Exception).

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

Если-же правило парности не соблюдать, то это может привести либо к преждевременной выгрузке (при лишнем FreeLibrary) библиотеки из памяти, либо к ее "застревании" там (при недостатке FreeLibrary).

При соблюдении же этого правила, можно не заботиться о возможной вложенности вызовов LoadLibrary / FreeLibrary.

Просмотр функций определенной DLL

Теперь посмотрим, как можно извлечь все имена функций из файлов PE формата, к которым и относится DLL. Структуру PE формата мы тут рассматривать не будем, следовательно, и исходник будет без пояснений.

Итак, создайте новый проект, бросьте на форму ListBox, в нём мы будем показывать имена функций.

Вот весь проект:

Unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) lb: TListBox; procedure FormCreate(Sender: TObject); private { Private declarations } cmdline: String; ImageBase: DWord; DosHeader: PImageDosHeader; PeHeader: PImageNtHeaders; PExport: PImageExportDirectory; pname: PDWord; name: PChar; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); procedure FatalOsError; begin ShowMessage(SysErrorMessage(GetLastError())); Abort; end; Var i: Integer; begin try if (ParamCount() IMAGE_DOS_SIGNATURE) then FatalOsError; PEHeader:= PImageNtHeaders(DWord(ImageBase) + DWord(DosHeader^._lfanew)); if (PEHeader^.Signature IMAGE_NT_SIGNATURE) then FatalOsError; PExport:= PImageExportDirectory(ImageBase + DWord(PEHeader^.OptionalHeader.DataDirectory.VirtualAddress)); pname:= PDWord(ImageBase + DWord(PExport^.AddressOfNames)); For i:= 0 to PExport^.NumberOfNames - 1 do begin name:= PChar(PDWord(DWord(ImageBase) + PDword(pname)^)); lb.Items.Add(name); inc(pname); end; finally FreeLibrary(ImageBase); end; except Application.ShowMainForm:= False; Application.Terminate; end; end; end.

Если вы захотите сами разобраться в коде и у вас что-то не будет получаться, то на нашем форуме вам обязательно помогут, заходите!

Прицепляем наш Viewer ко всем DLL

У нас есть готовая DLL с функцией, есть просмотрщик функций. Осталось добавить некой функциональности для удобства дальнейшей работы. Давайте сделаем это.... В проводнике открываем любую папку. Идем в Сервис -> Свойства папки... Переходим на закладку "Типы файлов". В списке ищем формат DLL. Если такого нет, то жмем кнопку "Создать" и в поле "Расширение" пишем - DLL. Жмем ОК. Находим созданный нами тип - DLL. Выделяем его и жмем "Дополнительно". Далее "Создать", в поле "Действии" пишем то, что будет отображаться в контекстном меню, например DLL Viewer. Через обзор ищем нашу программку.

Все готово!

Теперь при клике правой кнопкой мыши по файлу формата DLL в меню будет наш DLL Viewer. Выбираем его и смотрим все функции!

Это все, спасибо за внимание!

Не раз приходилось получать письма с просьбой рассказать о создании и использовании DLL в Delphi. В этой статье мы с Вами во всем разберемся и создадим свою библиотеку. Динамически связанные библиотеки (Dinamic Link Library) дают возможность различным приложениям при своей работе использовать общий набор ресурсов. Важно то, что процедуры и функции, помещенные в DLL, выполняются внутри того процесса, который их использует. DLL предоставляет для всех приложений одну единственную копию ресурса, который совместно используется всеми запросившими его приложениями, в отличие от подпрограмм, которые запускают для каждого вызвавшего их приложения свою отдельную копию. Так же в отличия DLL от подпрограмм можно включить и то, что DLL могут экспортировать только процедуры и функции, но не типы, константы и т.д.

Хочется привести отрывок из «Уроков по Дельфи» о структуре DLL в памяти:

DLL - библиотека, в отличие от приложения не имеет ни стека, ни очереди сообщений. Функции, помещенные в DLL, выполняются в контексте вызвавшего приложения, пользуясь его стеком. Но эти же функции используют сегмент данных, принадлежащий библиотеке, а не копии приложения. В силу такой организации DLL, экономия памяти достигается за счет того, что все запущенные приложения используют один модуль DLL, не включая те или иные стандартные функции в состав своих модулей. Часто, в виде DLL создаются отдельные наборы функций, объединенные по тем или иным логическим признакам, аналогично тому, как концептуально происходит планирование модулей (в смысле unit) в Pascal. Отличие заключается в том, что функции из модулей Pascal компонуются статически - на этапе линковки, а функции из DLL компонуются динамически, то есть в run-time.

Создание DLL

Структура DLL мало чем отличается от обычной структуры модуля в Object Pascal. Начинаться DLL должна со слова Library, за которым помещается название библиотеки. Функции и процедуры, которые DLL будет предоставлять другим пользователям (экспортировать), перечисляются после директивы exports.

Для каждой процедуры или функции можно указать ее номер с помощью директивы Index. Если номер будет отсутствовать, то компилятор проведет автоматическую индексацию. Вместо номера процедуры можно использовать уникальное имя, которое задается с помощью директивы name. Если же не указано ни имени функции, ни ее номера, то Дельфи воспримет это как экспорт по имени, которое будет совпадать с названием функции.

Библиотека может содержать также и код инициализации, который будет выполнен при ее загрузке. Он помещается между begin и end. Вот общая структура DLL:

Library First_Dll; uses <используемые модули>; <объявления и описания функций> exports <экспортируемые функции> <описание процедур и функций> begin <инициализационная часть> end.

Приведу примеры описания экспортируемых функций в разделе exports:

Exports Function1 index 2; Fucntion2 name "My_sqr"; Function3;

Как Вы уже догадались, имя функции может не совпадать с именем для экспорта!!!

Использование DLL

Модуль, в котором необходимо использовать процедуры и функции из DLL должен использовать директиву external. Существует два способа использования DLL (динамический и статический). В первом случае, приложение вызывающее функцию из DLL знает имя библиотеки и точку входа в нее, при этом предполагается, что библиотека не меняется. Во втором случае перед использованием DLL следует убедиться, что требуемая библиотека существует, и в ней есть необходимая подпрограмма.

Импортировать подпрограмму можно по ее имени и номеру. Поиск подпрограммы по номеру происходит быстрее, но всегда это удобно.

Ниже приведены примеры импорта функций из нашей First_DLL, которая была рассмотрена в примере:

{ импорт по специфицированному имени } Function ImportByName; external "First_DLL" name "My_sqr"; { импорт по индексу } Function ImportByOrdinal; external "First_DLL" index 2; { импорт по оригинальному имени } Function Fucntion3; external "First_DLL";

Мы рассмотрели статический метод использования DLL. Но в некоторых случаях заранее не известно какая именно потребуется библиотека, поэтому следует воспользоваться динамическим методом:

Uses WinTypes, WinProcs, ... ; type TMyProc = procedure ; var Handle: THandle; MyImportProc: TMyProc; begin Handle:=LoadLibrary("FirstDLL"); if Handle>=32 then { если <=32 - ошибка! } begin @MyImportProc:=GetProcAddress(Handle,"My_sqr"); if MyImportProc<>nil then ...... {здесь используем полученную функцию} end; FreeLibrary(Handle); end;

Но по-моему все что здесь написано не очень-то понятно и хочется реальных завершенных примеров. Я всегда расстраивался, когда в статьях было мало примеров, а одна только теория, поэтому предлагаю Вашему вниманию простой пример использования DLL.

Нажмите в меню File -> New и выберите DLL. Сохраните готовый шаблон, как предлагается, под именем Project1.dpr.

Ниже приведен его полный код:

Library Project1; uses SysUtils,Classes; Function Function1(x,y:integer):integer; export; bgin result:=x+y; end; Function Function2(x,y:real):real; export; var t:real; begin t:=exp(y*ln(x)); result:=t; end; exports Function1 index 1, Function2 name "My_sqr"; begin end.

Здесь две функции, первая вычисляет сумму двух чисел и экспортируется по номеру, а вторая вычисляет x в степени y и экспортируется по имени.

Теперь создадим новый проект и сохраним его под каким-нибудь другим именем, например, DemoDLL. Разместим на форме две кнопки, щелчок на первой из них будет вызывать первую процедуру, а щелчок на второй - вторую. Вот полный код этого демо-проекта:

Unit demo; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} function ImportSumm(x,y:integer):integer; external "Project1" index 1; //импорт по номеру function ImportSqr(x,y:real):real; external "Project1" name "My_sqr"; //импорт по имени procedure TForm1.Button1Click(Sender: TObject); var t:real; begin //Узнаем сколько же будет два в третьей степени t:=ImportSqr(2,3); Showmessage(FloatTostr(t)); end; procedure TForm1.Button2Click(Sender: TObject); var t:integer; begin //Узнаем сколько же будет 10+10 t:=ImportSumm(10,10); Showmessage(IntTostr(t)); end; end.

Программист Delphi, MySQL. Образование: высшее. Специальность: программное обеспечение информационных технологий.

DLL - Dynamic Link Library иначе динамически подключаемая библиотека, которая позволяет многократно применять одни и те же функции в разных программах. На самом деле довольно удобное средство, тем более что однажды написанная библиотека может использоваться во многих программах. В сегодняшнем уроке мы научимся работать с dll и конечно же создавать их!
Ну что ж начнём!

Для начала создадим нашу первую Dynamic Link Library! Отправляемся в Delphi и сразу же лезем в меню File -> New ->Other.
Перед нами появляется вот такое окошко:

Выбираем в списке Dynamic-Link Library (в версиях младше 2009 Delphi пункт называется DLL Wizard).

В результате у нас появляется лишь окно с кодом, заметьте никакой формы у нас здесь нет!
Теперь начинается самое интересное. Напишем наши первые процедуры в библиотеке.

library Project2;
//Вы, наверное уже заметили, что вместо program
//при создании dll используется слово library.
//Означающее библиотека.
uses
SysUtils, dialogs,
Classes; // Внимание! Не забудьте указать эти модули,
// иначе код работать не будет

{$R *.res}
{В ЭТУ ЧАСТЬ ПОМЕЩАЕТСЯ КОД DLL}

Procedure FirstCall; stdcall; export;
//Stdcall - При этом операторе параметры помещаются в стек
//справа налево, и выравниваются на стандартное значение
//Экспорт в принципе можно опустить, используется для уточнения
//экспорта процедуры или функции.

Begin
ShowMessage("Моя первая процедура в dll ");

End;

Procedure DoubleCall; stdcall; export;
Begin
ShowMessage("Моя вторая процедура ");
//Вызываем сообщение на экран
End;

Exports FirstCall, DoubleCall;
//В Exports содержится список экспортируемых элементов.
//Которые в дальнейшем будут импортироваться какой-нибудь программой.

begin
End.

На этом мы пока остановимся т.к. для простого примера этого будет вполне достаточно. Сейчас сохраняем наш проект, лично я сохранил его под именем Project2.dll и нажимаем комбинацию клавиш CTRL+F9 для компиляции библиотеки. В папке, куда вы сохранили dpr файл обязан появится файл с расширением dll, эта и есть наша только что созданная библиотека. У меня она называется Project2.dll

Займёмся теперь вызовом процедур из данной библиотеки. Создаём по стандартной схеме новое приложение. Перед нами ничего необычного просто форма. Сохраняем новое приложение в какую-нибудь папку. И в эту же папку копируем только что созданную dll библиотеку . Т.е. в данном примере Project2.dll

Теперь вам предстоит выбирать, каким способом вызывать функции из библиотеки. Всего существует два метода вызова.

Способ № 1
Пожалуй, это самый простой метод вызова процедур находящихся в библиотеке.
Идеально подходит для работы только с одной библиотекой.

Ну что поехали...
После ключевого слова implementation прописываем следующий код:

Procedure FirstCall; stdcall; external "Project2.dll" ;
// Вместо Project2.dll может быть любое имя библиотеки

Procedure DoubleCall; stdcall; external "Project2.dll" ;

Здесь, как вы уже наверное догадались, мы сообщаем программе названия наших процедур и говорим, что они находятся в dll библиотеке , в моем случае с именем Project2.dll

Теперь для того, что бы вызвать данные процедуры нам необходимо лишь вставить их названия в любое место кода, что мы сейчас и сделаем. Кидаем на форму 2 компонента Button с закладки Standart и создаем на каждой обработчик событий OnClick

OnClick первой кнопки:


Begin
FirstCall;
End;

OnClick второй кнопки:


Begin
DoubleCall; // Имя процедуры, которая находится в dll
End;

Вот и все!

Способ № 2:
Сложнее чем первый, но у него есть свои плюсы, а самое главное, что он идеально подходит для плагинов.
Для применения данного метода, первым делом объявляем несколько глобальных переменных:

Var
LibHandle: HModule; //Ссылка на модуль библиотеки
FirstCall: procedure; stdcall;
//Имена наших процедур лежащих в библиотеке.

DoubleCall: procedure; stdcall;

Затем после ключевого слова implementation напишем процедуру которая будет загружать нашу библиотеку:

Procedure LoadMyLibrary(FileName: String);
Begin
LibHandle:= LoadLibrary(PWideChar(FileName));
//Загружаем библиотеку!
// Внимание! PChar для версий ниже 2009 Delphi
If LibHandle = 0 then begin
MessageBox(0,"",0,0);
Exit;
End;
FirstCall:= GetProcAddress(LibHandle,"FirstCall ");
//Получаем указатель на объект
//1-ий параметр ссылка на модуль библиотеки
//2-ой параметр имя объекта в dll

DoubleCall:= GetProcAddress(LibHandle,"DoubleCall ");
If @FirstCall = nil then begin

MessageBox(0,"Невозможно загрузить библиотеку ",0,0);
Exit;
End;
If @DoubleCall = nil then begin
//Проверяем на наличие этой функции в библиотеке.
MessageBox(0,"Невозможно загрузить библиотеку ",0,0);
Exit;
End; End;

После чего на форме создаем, обработчик событий OnCreate, в котором с помощью только что созданной процедуры мы загрузим нашу библиотеку

Procedure TForm1.FormCreate(Sender: TObject);
Begin
LoadMyLibrary("Project2.dll ");
End;

Теперь опять же, для того, что бы вызвать необходимые процедуры из нашей библиотеки нам необходимо лишь вставить их названия в любое место кода. Для этого кидаем на форму 2 компонента Button с закладки Standart и создаем на каждой обработчик событий OnClick

OnClick первой кнопки:

Procedure TForm1.Button1Click(Sender: TObject);
Begin
FirstCall; // Имя процедуры, которая находится в dll
End;

OnClick второй кнопки:

Procedure TForm1.Button2Click(Sender: TObject);
Begin
DoubleCall; // Имя процедуры, которая находится в dll
End;

Ну и напоследок создаем обработчик событий OnDestroy на форме, в котором выгружаем dll библиотеку из памяти

Procedure TForm1.FormDestroy(Sender: TObject);
Begin
FreeLibrary(LibHandle);
//Выгружаем библиотеку из памяти.
End;

Вот и все! Второй способ получился довольно громоздкий, но его плюс в уточнении хранящегося объекта в библиотеке.

P.S. Хотите вперед всех остальных посетителей сайта получать свежие Видео уроки, Аудио подкасты, статьи по Delphi.
Участвовать в конкурсах и постепенно вливаться в нашу команду?!
Тогда прямо сейчас подписывайтесь на бесплатную мультимедийную рассылку сайта сайт
Нас уже больше чем 3500 человек!