На этом шаге мы рассмотрим создание DLL в Delphi.
Структура динамически подключаемой библиотеки практически такая же, как и структура проекта. Отличие состоит только в том, что в заголовке вместо зарезервированного слова program записывается зарезервированного слово library. Это слово указывает компилятору, что требуется создать выполняемый файл динамически подключаемой библиотеки, который должен иметь расширение .DLL, а не .ЕХЕ.
Приведем простейший демонстрационный пример использования DLL для создания пользователем собственной сервисной библиотеки процедур и функций.
library proba; { Important note about DLL memory management: ShareMem must be the first unit in your library's USES clause AND your project's (select Project-View Source) USES clause if your DLL exports any procedures or functions that pass strings as parameters or function results. This applies to all strings passed to and from your DLL--even those that are nested in records and classes. ShareMem is the interface unit to the BORLNDMM.DLL shared memory manager, which must be deployed along with your DLL. To avoid using BORLNDMM.DLL, pass string information using PChar or ShortString parameters. } uses SysUtils, Classes; {$R *.res} function Vect_Max (Vect: array of Integer; N:Word) : Integer; export; var Max : Integer; i : Word; begin Max := Vect[0]; for i := 1 to N-1 do if Vect[i] > Max then Max := Vect[i]; Result := Max; end; function Vect_Min (Vect: array of Integer; N:Word) : Integer; export; var Min : Integer; i : Word; begin Min := Vect[0]; for i := 1 to N-1 do if Vect[i] < Min then Min := Vect[i]; Result := Min; end; exports Vect_Max index 1, Vect_Min index 2; begin { Раздел инициализации отсутствует } end.
Рис.1. Вкладка New
Для получения DLL проект нужно сначала сохранить, а потом откомипилировать, выполнив, например, пункт меню Project | Build <Имя проекта>
В описании динамически связываемых библиотек важная роль принадлежит предложению exports (с буквой "s" в конце), которое рассмотрено на шаге 17, и процедурной директиве ехроrt (без буквы "s" в конце), которая указывается в заголовках экспортируемых из создаваемой DLL процедур и функций. Директива export принудительно использует для процедуры или функции дальний тип вызова и подготавливает ее для экспортирования, генерируя для процедуры/функции специальный код входа и выхода. Однако фактический экспорт процедуры/функции не произойдет до тех пор, пока она не будут указана в предложении exports описываемой библиотеки.
Операторы раздела инициализации выполняются, как и у модуля, однократно, но не при запуске программы, а при первоначальной загрузке библиотеки. Для определения потребности нахождения DLL в оперативной памяти служит, так называемый счетчик использования DLL. Для каждой DLL устанавливается свой счетчик использования DLL, который показывает, сколько программ в данный момент времени ее используют. Динамически загружаемая библиотека после загрузки хранится в памяти до тех пор, пока ее счетчик использования больше нуля. Когда все прикладные программы, использующие DLL, заканчивают работу, значение счетчика ее использования становится нулевым и DLL удаляется из памяти. Если какую-либо уже загруженную DLL начинает использовать еще одна программа, счетчик ее использования увеличивается, а операторы раздела инициализации повторно не выполняются.
Со следующего шага мы начнем знакомиться с использованием процедур и функций, находящихся в DLL.