На этом шаге мы рассмотрим статическую загрузку DLL.
Модуль может вызывать функции другого модуля, тот, в свою очередь, функции следующего и т. д. Например, приложение вызывает библиотеку, а эта библиотека вызывает функции другой библиотеки - так можно формировать длинные цепочки вызовов. Для вызова функции из другого модуля необходимо сначала загрузить ее в память, а затем определить адрес функции. Существует два способа загрузки и определения адреса функции - статический и динамический.
При статической загрузке для вызова другого модуля следует в какой-либо из секций описать функцию, вызываемую из DLL, одним из следующих способов:
function Addl(K: Integer): Integer; stdcall; external 'FirstLib.dll' name 'CalculateSum'; function Add1(K: Integer): Integer; stdcall; external 'FirstLib.dll' index 1;
Для тестирования необходимо описать в приложении внешнюю функцию одним из вышеупомянутых способов и создать, например, обработчик события OnClick кнопки, помещенной на форму вместе с компонентом TEdit:
procedure TForm1.Button1Click(Sender: TObject); var N: Integer; begin N := StrToInt(Edit1.Text); N := Add1(N); Edit1.Text := IntToStr(N); end;
Результат работы приложения изображен на рисунке 1.
Рис.1. Результат работы приложения
При щелчке на кнопке будет вызываться функция из DLL. Обратите внимание на изменение имени функции: из обработчика события OnCiick вызывается функция с именем Add1. Эта функция экспонируется в DLL под именем CalculateSum. В реализации DLL она имеет название AddOne.
При таком определении функции библиотека будет загружена немедленно после старта приложения и выгружена вместе с его завершением. В приведенном примере следует обратить внимание на то, что после имени библиотеки указано ее расширение (FirstLib.dll). Такая конструкция необходима для загрузки библиотеки в Windows NT, Windows 2000 и Windows XP - без расширения *.dll файл найден не будет. Для работы приложения под управлением Windows 95/98 указывать расширение не обязательно.
При поиске DLL для загрузки первоначально определяется, была ли данная библиотека уже загружена в память другим модулем. Если была - извлекается адрес вызываемой функции и затем передается приложению. Если же нет - операционная система начинает ее поиск на диске. При этом если в имени DLL путь не указан в явном виде, то операционная система ищет библиотеку в каталоге модуля, пытающегося загрузить DLL. Если не находит - то продолжает поиск в каталогах WINDOWS и WINDOWS | SYSTEM (или WINNT, WINNT | SYSTEM, WINNT | SYSTEM32). После этого происходит поиск в каталогах, определенных в переменной среды Path. Если операционная система обнаруживает библиотеку с заданным именем, она загружает эту библиотеку и приложение стартует. Если же нет - возникает исключение и приложение прекращает свою работу. Приложение также прекращает свою работу, если не найдена функция с данным именем (или индексом, если она импортируется по индексу).
На следующем шаге мы рассмотрим динамическую загрузку DLL.