Может ли Delphi использовать .dll только при необходимости? - PullRequest
6 голосов
/ 13 февраля 2012

Я добавил эти два метода в первый блок моего приложения 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 ]

16 голосов
/ 13 февраля 2012

Это средство, известное как задержка загрузки , было добавлено в 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.

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

15 голосов
/ 13 февраля 2012

В версиях 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;
...