Создание и использование библиотек подпрограмм



    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; Мы поможем в написании вашей работы!

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






Мы поможем в написании ваших работ!