启动应用程序后立即加载动态链接的 DLL

Dynamically linked DLL is loaded immediately after starting the application

我已经动态地 linked libhunspell.dll (HunSpell) 到我的应用程序。它有效,但有一个愚蠢的问题,我不知道它为什么会发生。

甚至在我使用 LoadLibrary("path\to\libhunspell.dll"); 加载和使用它之前,在应用程序启动时它会尝试自行加载库。如果我将 libhunspell.dll 放入我的主要可执行文件所在的路径,它可以加载它,否则它会在启动应用程序后立即报告错误 - 此应用程序未能启动,因为未找到 LIBHUNSPELL.DLL。重新安装应用程序可能会解决此问题。 并且应用程序无法启动。

我会理解 LoadLibrary 是否会使用无效路径,但这种情况会在可执行文件运行时立即发生,甚至在 WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int) 中的第一条语句执行之前(我试图放置一个断点它甚至没有到达它,所以这发生在之前)。

因此,我必须将 libhunspell.dll 放在与我的应用程序可执行文件相同的文件夹中,而不是我想要的路径中。

这可能很容易解决,虽然我不知道要找什么。

所以问题是 - 如何避免它立即加载并让它等到我使用 LoadLibrary 调用?

以下是我link编辑的方法,如果有帮助的话:

1) 在 Visual Studio 2015 中编译了 libhunspell.dll(我使用 /MT 选项静态 link 所以它没有 VC++ Redistributable 作为依赖)。

2) 使用 implib.exe -a -c -f libhunspell.lib libhunspell.dll

创建导入库 (libhunspell.lib)

3) link使用 #pragma comment(lib, "libhunspell.lib") 将其编辑到使用它的源 .cpp 单元(它是 RAD Studio 2010,因此需要 .lib 与较新版本不同)。

4) 稍后在同一个 .cpp 中使用 LoadLibrary 加载此库并使用它。

通过链接导入存根 (libhunspell.lib),OS 将为您加载 DLL,因为它现在是 static 依赖项。

一种方法是将库指定为延迟加载依赖项:/DELAYLOAD:libhunspell.lib 通过链接器选项。然后您可以在 DLL 上调用 LoadLibrary。

唯一的其他选择是停止在链接器步骤中包含 .lib,使其成为真正的动态依赖项。

我假设您为您的 DLL 添加了一个 *.lib 文件到项目。这是一种在 App 初始化(在创建表单之前)中完成的 "static" 链接。所以它有两个缺点。

  1. 您的 DLL 必须与 Apps EXE 文件
  2. 位于同一路径
  3. 有时DLL文件名被锁定(无法更改)

优点是你不需要为 DLL 加载做任何编码,因为 VCL 会为你做...所以你的应用程序不应该包含 LoadLibrary,GetProcAddress 调用您只需包含 *.h 文件和适当的导入声明 ...

对于动态链接,您需要从项目中删除 *.lib 并使用 WinAPI LoadLibrary + GetProcAddressDLL 加载为 josh poley 建议。举个例子:

  • Builder C++ calling VC++ class

注意 GetProcAddress 中存在/(是?)一个错误,在某些情况下阻止从 DLL 加载所有函数。特别是如果 DLL 有旧的遗留名称重整,函数的数量很高,并且 DLL 是在与所讨论的重整不兼容的编译器上创建的。