Содержание материала

Использование DLLProc

 

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

 

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

Code:

procedure MyFirstDLLProc(Reason: Integer);

begin

if Reason = DLL_PROCESS_DETACH then

   {DLL is unloading. Cleanup code here.}

end;

 

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

Code:

begin

DLLProc := @MyDLLProc;

{ Что-нибудь еще, что должно выполняться в

процессе инициализации библиотеки }

end.

  

Ниже представлен код, демонстрирующий один из возможных вариантов применения DLLProc.

Code:

library MyFirstDLL;

uses

SysUtils, Classes, Forms, Windows;

 

var

SomeBuffer: Pointer;

 

procedure MyFirstDLLProc(Reason: Integer);

begin

if Reason = DLL_PROCESS_DETACH then

   {DLL is выгружается из памяти.

   Освобождаем память, выделенную под буфер.}

   FreeMem(SomeBuffer);

end;

 

procedure HelloWorld(AForm: TForm);

begin

MessageBox(AForm.Handle, 'Hello world!',

'DLL Message Box', MB_OK or MB_ICONEXCLAMATION);

end;

 

{Какой-нибудь код, в котором используется SomeBuffer.}

 

exports

HelloWorld;

 

begin

{Ставим в соответствие переменной

DLLProc адрес нашей процедуры.}

DLLProc := @MyFirstDLLProc;

SomeBuffer := AllocMem(1024);

end.

  

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

 

DLL_PROCESS_DETACH

библиотека выгружается из памяти; используется один раз;

DLL_THREAD_ATTACH

в оперативную память загружается новый процесс, использующий ресурсы и/или код из данной библиотеки;

DLL_THREAD_DETACH

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

 

Добавить комментарий

Не использовать не нормативную лексику.

Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.

ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!


Защитный код
Обновить