Может ли Delphi использовать.dll только при необходимости?
Я добавил эти два метода в первый блок моего приложения Delphi 5.
function Inp(PortAddress: Integer): Integer; stdcall; external 'inpout32.dll' name 'Inp32';
procedure Output(PortAddress, Value: Integer); stdcall; external 'inpout32.dll' name 'Out32';
Однако я не хочу выпускать библиотеку inpout32 вместе с программным обеспечением, если им это явно не нужно. В настоящее время программа говорит "Не найдено" при выполнении, если они отсутствуют в корне или System32.
Пользователи будут вызывать эти методы только в том случае, если у них установлен определенный параметр, но он не собирается из INI-файла до тех пор, пока не будет использована входная библиотека.
Есть ли способ использовать эту библиотеку только тогда, когда это требуется, как это делают некоторые компоненты, а не объявлять ее так, как я?
2 ответа
В версиях Delphi до 2010 года вы должны использовать классическую динамическую загрузку. Рассмотрим этот типичный (и простой) пример вызова Beep
функция от Kernel32.dll
(конечно, вы не должны указывать путь в реальном коде!):
type
TBeepFunc = function(dwFreq: DWORD; dwDuration: DWORD): BOOL; stdcall;
procedure TForm4.FormClick(Sender: TObject);
var
lib: HMODULE;
prc: TBeepFunc;
begin
lib := LoadLibrary('C:\WINDOWS\System32\Kernel32.dll');
if lib = 0 then RaiseLastOSError;
try
@prc := GetProcAddress(lib, 'Beep');
if Assigned(prc) then
prc(400, 2000)
else
ShowMessage('WTF? No Beep in Kernel32.dll?!');
finally
FreeLibrary(lib);
end;
end;
Это средство, известное как отложенная загрузка, было добавлено в Delphi 2010.
Используя ваш код в качестве примера, вы можете написать свой импорт следующим образом:
function Inp(PortAddress: Integer): Integer; stdcall;
external 'inpout32.dll' name 'Inp32' delayed;
Привязка к этой внешней функции будет выполняться только при первом вызове функции. Если привязка не выполняется, возникает исключение во время выполнения.
Ты можешь использовать SetDliNotifyHook
а также SetDliFailureHook
чтобы настроить поведение при загрузке с задержкой, вам потребуется еще более детальный контроль.
Некоторые статьи блога, дополняющие документацию по продукту:
- Аллен Бауэр: Прокрастинаторы объединяются... В конце концов!
- Аллен Бауэр: Исключительная прокрастинация
- Доктор Боб: Delphi 2010 библиотеки с отложенным динамическим соединением
На старых версиях Delphi вы можете использовать LoadLibrary
а также GetProcAddress
, Или, если вы хотите что-то немного более гладкое, я могу от всей души порекомендовать класс задержки загрузки Hallvard Vassbotn, который он описывает в этой статье блога. Этот код оборачивает все котлы вызова LoadLibrary
а также GetProcAddress
и только немного более громоздким в использовании, чем новая встроенная функция Delphi 2010.
Я успешно пользовался библиотекой Гальварда много лет. Одно небольшое предостережение заключается в том, что он не является потокобезопасным, поэтому, если несколько потоков пытаются связать функцию одновременно, тогда код может завершиться ошибкой. Это достаточно легко исправить, добавив внутренние блокировки к коду Халварда.