QuickSort: TQuickSortProc; // указатель на функцию QuickSort

LibHandle: HModule; // описатель библиотеки

Arr: array [0..9] of Integer;

I: Integer;

Begin

LibHandle:= LoadLibrary('SortLib.dll');

if LibHandle <> 0 then

Begin

@BubleSort:= GetProcAddress(LibHandle, 'BubleSortIntegers');

@QuickSort:= GetProcAddress(LibHandle, 'QuickSortIntegers');

if (@BubleSort <> nil) and (@QuickSort <> nil) then

Begin

Randomize;

for I:= Low(Arr) to High(Arr) do Arr[I]:= Random(100);

BubleSort(Arr);

End

else Writeln('Ошибка отсутствия процедуры в библиотеке.');

FreeLibrary(LibHandle);

End

else Writeln('Ошибка загрузки библиотеки.');

End.

В программе определены два процедурных типа данных, которые по списку параметров и правилу вызова (stdcall) соответствуют подпрограммам сортировки BubleSort и QuickSort в библиотеке:

type

TBubleSortProc = procedure (var Arr: array of Integer); stdcall;

TQuickSortProc = procedure (var Arr: array of Integer); stdcall;

Эти типы данных нужны для объявления процедурных переменных, в которых сохраняются адреса подпрограмм:

Var BubleSort: TBubleSortProc;

QuickSort: TQuickSortProc;

В секции var объявлена также переменная для хранения целочисленного описателя библиотеки, возвращаемого функцией LoadLibrary: LibHandle: HModule;

Программа начинает свою работу с того, что вызывает функцию LoadLibrary, в которую передает имя файла DLL-библиотеки. Функция возвращает описатель библиотеки, который сохраняется в переменной LibHandle: LibHandle:= LoadLibrary('SortLib.dll');

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

@BubleSort:= GetProcAddress(LibHandle, 'BubleSortIntegers');

@QuickSort:= GetProcAddress(LibHandle, 'QuickSortIntegers');

Использование символа @ перед именем каждой переменной говорит о том, что выполняется не вызов подпрограммы, а работа с ее адресом. Если этот адрес отличен от значения nil, значит подпрограмма с указанным именем была найдена в библиотеке и ее можно вызвать путем обращения к процедурной переменной:

if (@BubleSort <> nil) and (@QuickSort <> nil) then

begin

...

BubleSort(Arr);

...

end

По окончании сортировки программа выгружает библиотеку вызовом функции FreeLibrary.

Динамический импорт в сравнении со статическим требует значительно больше усилий на программирование, но он имеет ряд преимуществ:

·Более эффективное использование ресурсов оперативной памяти по той причине, что библиотеку можно загружать и выгружать по мере надобности;

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

Динамический импорт отлично подходит для работы с библиотеками драйверов устройств. Он, например, используется самой средой Delphi для работы с драйверами баз данных.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: