Может ли 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 вы можете использовать LoadLibrary а также GetProcAddress, Или, если вы хотите что-то немного более гладкое, я могу от всей души порекомендовать класс задержки загрузки Hallvard Vassbotn, который он описывает в этой статье блога. Этот код оборачивает все котлы вызова LoadLibrary а также GetProcAddress и только немного более громоздким в использовании, чем новая встроенная функция Delphi 2010.

Я успешно пользовался библиотекой Гальварда много лет. Одно небольшое предостережение заключается в том, что он не является потокобезопасным, поэтому, если несколько потоков пытаются связать функцию одновременно, тогда код может завершиться ошибкой. Это достаточно легко исправить, добавив внутренние блокировки к коду Халварда.

Другие вопросы по тегам