Program TestDynamicImport;
Uses Windows;
Type
TBubleSortProc = procedure (var Arr: array of Integer); stdcall;
TQuickSortProc = procedure (var Arr: array of Integer); stdcall;
Var
BubleSort: TBubleSortProc; // указательнафункцию BubleSort
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 для работы с драйверами баз данных.
Дата добавления: 2015-09-07; просмотров: 1003;