如果需要,Delphi是否只能使用.dll?

not*_*aho 6 delphi dll delphi-5

我已将这两种方法添加到我的Delphi 5应用程序的第一个单元中.

function Inp(PortAddress: Integer): Integer; stdcall; external 'inpout32.dll' name 'Inp32';

procedure Output(PortAddress, Value: Integer); stdcall; external 'inpout32.dll' name 'Out32';
Run Code Online (Sandbox Code Playgroud)

但是,除非他们明确需要,否则我不想使用该软件发布inpout32库.目前程序在执行时说"未找到",除非它们存在于根或System32中.

用户只有在设置了特定选项时才会调用这些方法,但在使用inpout库之前,不会从.ini文件中收集这些方法.

有没有办法只在某些组件需要时才使用这个库,而不是按照我的方式声明它?

Dav*_*nan 16

这种被称为延迟加载的工具在Delphi 2010中添加.

以您的代码为例,您可以像这样编写导入:

function Inp(PortAddress: Integer): Integer; stdcall; 
    external 'inpout32.dll' name 'Inp32' delayed;
Run Code Online (Sandbox Code Playgroud)

只有在首次调用该函数时才会执行对此外部函数的绑定.如果绑定失败,则在运行时引发异常.

如果需要更细粒度的控制,可以使用SetDliNotifyHookSetDliFailureHook自定义延迟加载行为.

一些博客文章补充产品文档:


在旧版本的Delphi上,您可以使用LoadLibraryGetProcAddress.或者,如果你想要一点点光滑,我可以衷心地推荐Hallvard Vassbotn的延迟加载等级,他在这篇博客文章中描述了这一点.这段代码包含了所有调用的样板,LoadLibrary并且GetProcAddress使用起来比新的Delphi 2010内置功能稍微麻烦一些.

我成功地使用了Hallvard的图书馆多年.一个小问题是它不是线程安全的,所以如果多个线程同时尝试绑定到一个函数,那么代码就会失败.通过向Hallvard的代码添加内部锁,这很容易解决.


And*_*and 16

在2010年之前的Delphi版本中,您必须使用经典的动态加载.考虑这个典型(简单的)例子调用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;
Run Code Online (Sandbox Code Playgroud)

  • 在D5中`RaiseLastOSError` =`RaiseLastWin32Error` (5认同)