Создание и использование библиотек подпрограмм
Delphi позволяет программисту поместить свои функции и процедуры в отдельный модуль, а затем использовать процедуры и функции модуля в своих программах, указав имя модуля в списке модулей, необходимых программе (инструкция uses).
Чтобы приступать к созданию модуля формы (в ответ на вопрос о необходимости сохранения модуля следует выбрать No. т.е. модуль, соответствующий закрытой форме, сохранять не надо). Затем из меню File нужно выбрать команду New l Unit. В результате открывается окно редактора кода, в котором находится сформированный Delphi шаблон модуля.
Шаблон модуля:
unit Unit1;
interface implementation
end.
Начинается модуль заголовком - инструкцией unit, в которой указано имя модуля. Во время сохранения модуля это имя будет автоматически заменено на имя, указанное программистом.
Слово interface отмечает раздел интерфейса модуля. В этот раздел программист должен поместить объявления находящихся в модуле процедур и функций, которые могут быть вызваны из других модулей, использующих данный.
В раздел implementation (реализация) нужно поместить процедуры и функции, объявления в разделе interface.
Сохраняется модуль обычным образом, т.е выбором из меню File команды Save. Вместе с тем, для модулей повторно используемых процедур и функций лучше создавать отдельную папку, назвав ее, например Units.
Для того чтобы в программе могли применяться функции и процедуры модуля, программист должен добавить этот модуль к проекту и указать имя модуля в списке используемых модулей (обычно имя модуля программиста помещают в конец сформированного Delphi списка используемых модулей).
|
|
После добавления имени модуля в список модулей, используемых приложением, сам модуль нужно добавить в проект. Для этого из меню Project надо выбрать команду Add to Project и в открывшемся диалоговом окне - имя файла модуля. В результате добавления модуля к проекту в окне редактора появится вкладка с текстом добавленного к проекту модуля.
Увидеть структуру проекта можно в окне Project Manager, которое появляется в результате выбора соответствующей команды из меню View.
После добавления модуля к проекту и включения его имени в список используемых модулей (инструкция uses) можно выполнить компиляцию программы.
Тема 2.8 Создание DLL- библиотек в Delphi
1. Понятие и особенности DLL-библиотек.
2.структура проекта DLL.
Понятие и особенности DLL-библиотек
Динамически подключаемые библиотеки (DLL-Dynamic Link Library)- это универсальный механизм интегрирования в разрабатываемую программу процедур и функций, написанных другими программистами и, в общем случае, на других, чем Object Pascal,языках программирования.
|
|
Динамически подключаемые библиотеки реализуются в виде исполняемых модулей, и аналогично обычным для Object Pascal модулям содержат готовые к работе процедуры, функции и/или ресурсы. Но существует и принципиальные отличия:
1. В отличие от обычных модулей Delphi DLL не в состоянии поставлять в программу переменные, константы и типы, так как создатели DLL могут использовать не типизированные языки программирования, например, язык ассемблера. Вследствие этого DLL могут использовать в программу классы. Для экспорта классов используется пакеты.
2. Обычные модули связываются с программой на этапе компоновки, т.е статически. При этом, если один и тот же модуль использует более чем одна программа в память компьютера загружаются несколько одинаковых экземпляров кода. В отличие от этого DLL подключаются к программе в момент ее использования, т.е динамически. В памяти будет лишь один экземпляр разделяемого программами кода.
3. Изменение любой DLL в большинстве случаев не требует перекомпиляции использующей ее программы.
4. Одну DLL могут использовать программы, написанные на разных языках.
Структура проекта DLL
Для создания динамической библиотеке в Репозиции Delphi имеется специальный шаблон - DLL Wizardрасположенный на странице New Репозиция. В отличие от проекта обычного приложения, проект DLL состоит всего из одного исходного файла. Впоследствии к нему можно добавлять отдельные модули и формы.
|
|
Исходный файл проекта динамической библиотеке
library Project1;
uses SysUtils, Clases;
{$R*.res}
begin
...
end.
Для определения типа проект используются ключевое слово library.
За словом Library следует правильный идентификатор, но в отличие от объявления модуля он не обязан совпадать с именем файла: имя DLL
определяется именем DLL-файла, а не идентификатором, следующим за Library. При компиляции такого проекта динамической библиотеки создается файл с расширением dll.
Сразу за заголовками экспортируемых подпрограмм должна следовать директива Export, которая, указывает компилятору на необходимость выработки специального кода пролога/эпилога.
В разделе описаний DLL могут объявляться типы (в том числе и классы), константы и переменные, но они остаются скрытыми от вызывающей программы и могут использоваться только внутри DLL. В разделе описаний помимо стандартный для обычной программы объявлений используются специальный радел объявления экспортируемых программ. Этот раздел начинается зарезервированным словом Exports, за которым через запятую перечисляются имена экспортируемых подпрограмм.
|
|
Блок begin...endназывается блоком инициализации библиотеке и предназначен для размещения кода, который автоматически выполняется при загрузке DLL. Между секцией uses и блоком инициализации можно располагать исходный код функций динамической библиотеки и их объявления. При этом можно использовать любые конструкции языка Object Pascal (Delphi), а также применять формы и компоненты.
Для каждой подпрограммы помимо имени в заголовке DLL указывается присвоенный ей целочисленный индекс (целое число в диапазоне от 0 до 32767). Это позволяет вызывающей программе ссылаться не на имя, а на индекс подпрограммы и тем самым уменьшить затраты времени на установление с ней связи.
Delphi предоставляет возможность определить внешнее имя экспортируемой подпрограммы отличное от ее настоящего имени. Для этого в списке Exports добавляется слово name и внешнее имя в апострофах:
Exports
MyFune index I name 'NEWFUNC';
Функции из DLL-библиотеке могут вызываться как из приложений, разработанных в Delphi, так и из приложений, написанных на других языках программирования, таких, как C++.
Порядок выделения памяти под параметры и освобождения ее различен для разных языков программирования. Для того чтобы не возникла ошибка времени выполнения, объявления функции в DLL- библиотеке и ее объявление в приложении должны использовать одинаковый механизм передачи параметров. При объявлении процедуры или функции может быть указан один из следующих механизмов передачи параметров:
1.register,
2.pascal,
3.cdecl
4.stdcall,
5.safecall.
Способ передачи параметров указывается через точку с запятой после описания функции. Например: function F1 (X,Y,Z: Ral): Heal; stdcall.
Различные способы передачи параметров определяют порядок передачи параметров (слева направо или справа налево), а также указываются, кто будет освобождать память стека (вызываемая или вызывающая процедура). При использовании DLL-библиотек в качестве компонентов, вызываемых из приложений на других языках программирования, следует использовать соответствующий модификатор вызова. Для приложений на С++ применяется модификатор вызова stdcall.
Для того чтобы функцию, описанную в DLL-библиотеке, можно было вызвать из другого приложения, эту функцию следует экспортировать. Список всех экспортируемых функций указывается в секции exports через запятую и завершается символом точка с запятой.
Экспорт функций может выполняться тремя способами:
- по имени функции, используемой в DLL-библиотеке;
- по имени функции. заданному как имя экспорта;
- по присвоенному функции индексу.
Для того чтобы присвоить функции некоторый индекс, его следует указать в секции exports после имени функции с ключевым словом index. Для того чтобы экспортируемая функция вызывалась по имени, отличном от имени, используемого в DLL-библиотеке, в секции exports после имени функции следует указать ключевое слово name и новое имя экспорта для данной функции.
DLL - библиотека не является выполняемым модулем. Для получения ее кода достаточно произвести команду меню Project/<имя _проекта> или нажав клавиши Ctrl+F9.
Подключение DLL-библиотек
DLL-библиотека может подключаться или статически, или динамически. При подключении DLL-библиотеки она загружается в память приложения. При статическом запуске подключении DLL-библиотека загружается один раз при запуске приложения.
На всем протяжении выполнения приложения имя функции, импортируемой из DLL-библиотеки, которая была подключена статически, указывает на одну и ту же функцию (точку входа в DLL) в одной и той же DLL.
Все функции из DLL-библиотеки, которые будут использоваться в приложении первоначально, должны быть объявлены как внешние. При этом следует указать, если требуется, модификатор вызова. Если функция вызывается по индексу, то для нее следует задать имя, используемое в приложении, и индекс функции в DLL-библиотеке.
Объявления внешних функций выполняется в секции implementation до использования этих функций.
Объявление внешний функции с ключевым словом external определяет, что будет использовано статическое связывание.
Динамическое подключение DLL-библиотеки. В отличие от статического подключения DLL-библиотеки, выполняемого в момент загрузки приложения, динамическое подключение DLL-библиотеки может быть выполнено в любой точке выполнения программы. После вызова функции из DLL-библиотеки ее можно отключит. При одновременном использовании нескольких DLL-библиотек это дает ощутимую экономию памяти. Для динамического подключения DLL-библиотеки используются функции Windows API. Windows API - это набор стандартных функций , используемый для реализации взаимодействия с операционной системой.
При вызове функции из динамически подключаемой DLL-библиотеки вместо определения имени функции как external в случае статического связывания следует определить новый тип, соответствующий типу вызываемой функции, и создать переменную данного типа. Определение типа функции или процедуры описывается так:
новый тип=function(список_параметров|тип_функции;модификатор_доступа; или: новый_тип=procedure(список_параметров)/модификатор_доступа;
Для того, чтобы выполнить вызов функции из динамически подключаемой 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-библиотеки и имя подключаемой функции.
Например: ...:=GetProcAddress(h,'F1'>;
7. Если адрес функции получен, то значение адреса (в нашем примере @MyFl) не должно быть равно nil.
8. На этом этапе можно выполнять вызов функции из динамически подключенной DLL-библиотеки.
9. Для освобождения и соответственно выгрузки DLL-библиотеки вызовите метод FreeLibrary, выполняющий отключение DLL-библиотеки.
Динамические библиотеки могут содержать не только исполняемый код, проводящий некоторые вычисления, но и ресурсы. Чаще всего бывает необходимо распространять вместе с DLL формы, обеспечивающие работу процедур и функций. Приемы работы с формами в проектах динамических библиотек ничем не отличаются от тех приемов в проектах обычных приложений.
Единственная особенность заключается в то, что любая форма в DLL должна рассматриваться как создаваемая вручную, а не автоматически. При этом в процедуру, создающую форму, должен быть передан указатель на владельца будущей формы.
Например, процедура showDemoForm из рассматриваемой нами библиотеки DataCheck выглядит так:
procedure ShowDemoForm(AOwner: TComponent);
begin
DemoForm := TDemoForm.Create(AOwner);
DemoForm.ShowModal;
DemoForm.Free;
end;
Дата добавления: 2018-04-05; просмотров: 1803; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!