Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


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

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

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

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

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

• register,

• pascal,

• cdecl,

• stdcall,

• safecall.

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

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

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

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

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

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

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

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

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

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

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

Пример:

library Projectl;

uses

SysUtils, Classes;

{$R *.res}

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

begin

F1:=X+Y;

end;

 

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

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

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

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

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

"

Пример:

unit Unitl;

interface

uses

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

Controls, Forms, Dialogs, StdCtrls;

Type

TForml = class(TForm)

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

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

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

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

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

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

procedure ButtonlClickfSender: TObject);

procedure Button2Click(Sender: TObject);

private

{ Private declarations }

public

(Public declarations }

end;

var

Forml: TForml;

implementation

{$R *.dfm)

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

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);

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

begin

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

end;

procedure TForml.Button2Click(Sender: TObject);

begin

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

end;

end.

 

Динамическое подключение 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-библиотеки.

Пример:

unit Unitl;

interface

uses

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

Controls, Forms, Dialogs, StdCtrls;

type

TForml = class(TForm)

iditl: TEdit;

Edit2: TEdit;

Edit3: TEdit;

Button3: TButton;

procedure Button3Click[Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

TMyFl=function(i,j:Integer):Integer; stdcall; {Создание типа

функции)

var

Forml: TForml;

MyFl: TMyFl; (Объявление переменной типа функции]

implementation

{$R *.dfm}

procedure TForml.Button3Click(Sender: TObject);

var

h: Integer;

begin

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

if h <> 0 then

begin

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

if @MyFl <> nil then

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

StrToInt(Edit2.Text)));

FreeLibrary(h);

end;

end;

end.

 

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

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

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

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

Пример:

library Projectl;

uses

SysUtils,

Classes,

Unitl_DLL in 'Unitl_DLL.pas' {Forml};

{$R '.res}

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

begin

Form1:=TForml.Create(F);

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

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

Form1.ShowModal();

(Первый параметр используется для возвращаемого значения}

Z:=StrToInt(Form1.Edit1.Text);

Form1.Free;

end;

exports MyModalForm;

end.

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

DLL-библиотеки, отображающей модальный диалог.

Пример:

unit Unitl;

interface

uses

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

Controls, Forms,

Dialogs, StdCtris;

type

TForml = class(TForml

Button4: TButton;

Edit4: TEdit;

procedure Button4Click(Sender: TObject);

private

public

end;

TMyModalFora=procedure(var Z:Integer; F:TForml); stdcall;

var

Forml: TForml;

MyModalForm: TMyHodalForm; (Переменная типа

вызываемой процедуры]

implementation

{$R *.dfml

procedure TForml.Button4Click(Sender: TObject);

var

244 Глава 6

h: Integer;

ii: Integer; {Для сохранения возвращаемого значения)

begin

ii:=0;

h:=LoadLibrary('Projectl.dll'};

if h о 0 then

begin

@MyModalForm:=GetProcAddress(h,'HyModalForm');

if @MyModalForm о nil then

MyModalForm(ii,Forml);

FreeLibrary(h);

end;

Edit4.Text;= IntToStr(ii); {Отображение значения, возвращаемого

функцией MyModalForm из DLL-библиотеки)

end;

end.

 





Поделиться с друзьями:


Дата добавления: 2016-11-19; Мы поможем в написании ваших работ!; просмотров: 1806 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Начинать всегда стоит с того, что сеет сомнения. © Борис Стругацкий
==> читать все изречения...

2389 - | 2156 -


© 2015-2025 lektsii.org - Контакты - Последнее добавление

Ген: 0.013 с.