Явная загрузка библиотек
4.1. Загрузите дополнение, написанное в прошлом разделе, которое использует динамическую библиотеку. В основном модуле уберите объявление функции ShowAbout. Теперь в роздiлi type напишите объявление нового типа :
ShowA = function (Handle: THandle) : LongInt; stdcall;
Здесь мы объявляем новый тип ShowA, который равняется функции с параметрами функции showAbout из динамической библиотеки. Параметры должны быть точными, как при объявлении, иначе могут возникнуть проблемы.
4.2. Для события Onclick первой кнопки, написать следующий код.
procedure TForml.ButtonlClick (Sender: TObject);
var
DLLHandle: THandle;
sa: ShowA;
begin
if f> 0 then
FreeAbout (f);
DLLHandle: = LoadLibrary ( 'Proj ectDLL.DLL');
if DLLHandle = 0 then
exit; / / Библиотека не погрузилась
@ sa: = GetProcAddress (DLLHandle, 'ShowAbout');
if @ sa = nil then
exit; / / Функция не найдено
f: = sa (Handle);
FreeLibrary (DLLHandle);
end;
Здесь объявлены два локальные переменные:
DLLHandle - будет храниться указатель на зафуженную библиотеку;
sa - имеет тип ShowA, то есть тип функции из библиотеки.
В начале кода выполняется уже знакомая проверка переменной f. Если она больше нуля, то окно уже показывалось, и нужно освободить память от старого окна, прежде чем создавать новое.
Дальше вызывается функция LoadLibrary. Эта API -функція загружает отмеченную как параметр динамическую библиотеку в память. Результатом выполнения является указание на загруженную библиотеку. Этот указатель храним в переменной DLLHandie. После этого нужно проверить, если указатель DLLHandie равняется нулю, то библиотека не погрузилась.
Теперь нужно получить адрес функции showAbout у загруженной памяти, чтобы выполнить функцию. Для этого вызывается функция GetProcAddress. Опции нужно передать два параметра:
- Указатель на загруженную библиотеку;
- Имя искомой процедуры.
Результатом будет адрес искомой функции, и мы его храним по адресу переменной @ sa. Теперь sa указывает по адресу, за которым загруженная процедура ShowAbout из динамической библиотеки. Единственное, что надо проверить, - корректность адреса. Если он равняется nil, то процедура не найдена (возможно, что это старая версия библиотеки или неправильно указано имя).
Если все нормально, то мы вызываем функцию через переменную f : = sa (Handle), почти так же, как это делалось раньше. Результат выполнения функции хранится в переменной f.
Последняя строка кода выгружает динамическую библиотеку из памяти - FreeLibrary.
Точка входа
В библиотеках есть одна глобальная переменная, которая существует всегда, и ее имя DLLProc. Это не просто переменная, а указатель на процедуру. За умалчиванием он равняется nil, но если сюда записать адрес реальной процедуры, то эта процедура может отзываться на определенные события, которые происходят в библиотеке. В процедуре можно регистрировать последующие события:
DLL_PROCESS_ATTACH - это событие генерируется при загрузке библиотеки.
DLL_PROCESS_DETACH - это событие генерируется при выгрузке библиотеки.
DLL_THREAD_ATTACH - при создании нового потока.
DLL_THREAD_DETACH - при отключении нового потока.
5.1. Откройте библиотеку, написанную в предыдущем разделе. Теперь добавляйте к ней код.
library ProjectDLL;
uses
SysUtils,
Classes,
Windows,
dialogs,
Unit1 in 'Unit1.pas' (Form1);
($ R *. RES)
exports ShowAbout index 10;
exports FreeAbout index 11;
procedure DLLEntryPoint (dwReason: DWord);
begin
case dwReason of
DLL_PROCESS_ATTACH : ShowMessage ( 'Attach to process');
DLL_PROCESS_DETACH : ShowMessage ( 'Detach to process');
DLL_THREAD_ATTACH : ShowMessage ( 'Thread attach to process');
DLL_THREAD_DETACH : ShowMessage ( 'Thread detach to process');
end;
end;
begin
DLLProc: = @ DLLEntryPoint;
DLLEntryPoint (DLL_PROCESS_ATTACH);
end.
В разделе uses появилось объявление двух новых модулей - windows и dialogs. Без них код не скомпіліруется. Немного дальше появилась процедура DLLEntryPoint с одним параметром, в котором будет передаваться событие, которое случилось. Внутри процедуры оператором case проверяется тип пришло сообщение и в зависимости от этого выводится сообщение.
Между begin и end библиотеки переменной DLLProc присваивается процедура. После этого вызываем ее и как параметр указываем событие DLL PROCESS ATTACH.
Дата добавления: 2016-02-27; просмотров: 561;