logo
Дипломы2 / Андрей / Чужие дипломы / Диплом1 / диплом

4.3. Использование библиотек (dll)

Библиотека - это один или несколько логически законченных фрагментов кода, сохраненных в файле с расширением .dll. Этот код может быть запущен на выполнение в процессе функционирования какой-либо другой программы, но сама DLL не является исполняемым файлом.

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

Разработка динамических библиотек не представляет собой некий сверхсложный процесс. Итак, рассмотрим те особенности создания DLL , которые необходимо знать для создания шлюза.

Как и любой другой модуль, модуль динамической библиотеки имеет фиксированный формат. Рассмотрим на основе листинга, представленного ниже.

libraryMyDLL;

uses

SysUtils,

Classes,

Forms,

Windows;

procedure Summ(a,b:integer):integer; export; stdcall;

begin

Result:=a+b;

end;

exports

Summ;

begin

end.

Первое, на что следует обратить внимание, это ключевое слово library. Оно определяет этот модуль как модуль библиотеки DLL. Далее идет название библиотеки. В нашем примере мы имеем дело с динамической библиотекой, содержащей единственную функцию Summ. Ключевое словоexportsсигнализирует компилятору о том, что перечисленные ниже функции и/или процедуры должны быть доступны из вызывающих приложений. В конце модуля можно увидеть ключевые словаbeginиend. Внутри данного блока можно поместить код, который должен выполняться в процессе загрузки библиотеки.

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

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

Уже говорилось, что код инициализации динамической библиотеки может быть помещен в блок begin...end. Однако кроме этого зачастую необходимо предусмотреть некоторые действия, выполняемые в процессе выгрузки DLL из оперативной памяти. В отличии от других типов модулей, модуль DLL не имеет ни секцииinitialization, ни секцииfinalization. К примеру, можно динамически выделить память в главном блоке, однако не понятно, где эта память должна быть освобождена. Для решения этой проблемы существуетDLLProc- специальная процедура, вызываемая в определенные моменты функционирования DLL.

Для начала следует сказать о самой причине существования DLLProc. Динамическая библиотека получает сообщения от Windows в моменты своей загрузки и выгрузки из оперативной памяти, а также в тех случаях, когда какой-нибудь очередной процесс, использующий функции и/или ресурсы, хранящиеся в библиотеке, загружается в память. Такая ситуация возможно в том случае, когда библиотека необходима для функционирования нескольких приложений. А для того, чтобы имелась возможность указывать, что именно должно происходить в такие моменты, необходимо описать специальную процедуру, которая и будет ответственна за такие действия. К примеру, она может выглядеть следующим образом:

procedure MyDLLProc(Reason: Integer);

begin

if Reason = DLL_PROCESS_DETACH then

{DLL is unloading. Cleanup code here.}

end;

Однако системе совершенно не очевидно, что именно процедура MyDllProcответственна за обработку рассмотренных выше ситуаций. Поэтому необходимо поставить в соответствие адрес процедуры глобальной переменнойDLLProc. Это необходимо сделать в блокеbegin...endпримерно так:

begin

DLLProc := @MyDLLProc;

end.

Как можно увидеть, в качестве признака того или иного события, в результате которого вызывается процедура MyFirstDll, является значение переменнойReason. Ниже приведены возможные значения этой переменной.

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

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

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

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

Function Summ(a,b: integer):integer; external “mydll.dll”;

Ключевое слово external сообщает компилятору, что данная процедура может быть найдена в динамической библиотеке (в нашем случае - mydll.dll). Далее вызов этой процедуры выглядит следующим образом:

...

i:=4;

c:=Summ(5,i);

...

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