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

问题描述 投票:0回答:2

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

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

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

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

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

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

这是我如何链接,如果它可以帮助:

1)在Visual Studio 2015中编译了libhunspell.dll(我使用/ MT选项将其静态链接,因此它没有VC ++ Redistributable作为依赖项)。

2)使用implib.exe -a -c -f libhunspell.lib libhunspell.dll创建导入库(libhunspell.lib)

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

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

dll c++builder loadlibrary hunspell
2个回答
3
投票

通过链接导入存根(libhunspell.lib),操作系统将为您加载DLL,因为它现在是一个静态依赖项。

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

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


1
投票

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

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

优点是您不需要对DLL加载进行任何编码,因为VCL为您执行...因此您的应用程序不应包含LoadLibrary,GetProcAddress调用您只需包含带有propper import声明的*.h文件...

对于动态链接,您需要从项目中删除*.lib,并使用WinAPI LoadLibrary + GetProcAddress加载您的DLL,如josh poley建议的那样。这是一个例子:

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

© www.soinside.com 2019 - 2024. All rights reserved.