QT 中的延迟 DLL 加载

Posted

技术标签:

【中文标题】QT 中的延迟 DLL 加载【英文标题】:Delayed DLL load in QT 【发布时间】:2012-04-12 13:57:59 【问题描述】:

QT 中是否可以延迟加载 DLL? 例如,我的程序依赖于某个第三方 DLL,我想将其删除。

我应该在 .pro 文件中写什么来消除依赖关系?

我可以将 DLL 存储在资源中吗?

我可以“全局”加载 DLL 吗?因此,DLL 中的某些函数(例如 func1)将在我的代码中保留为 func1。

【问题讨论】:

【参考方案1】:

是的,您想使用QLibrary 类。它专门用于在运行时加载共享库。

在这种情况下,您的 .pro 文件中不需要任何内容​​。但是,您需要确保 DLL 在目标计算机上可用。它需要位于系统可以找到它的位置(Windows 上的 PATH,Linux 上的 LD_LIBRARY_PATH,Mac 上的 DYLD_LIBRARY_PATH),或者您可以提供应用程序的绝对路径。

如果您查看文档,您将了解如何将库函数映射到代码中的函数指针,以便“func1()”指向库中的函数。

QLibrary Class Reference

[编辑]

这是从资源生成的临时文件加载 dll 的概念验证。 IMO,这是一个非常糟糕的主意,但它至少适用于我的 Windows 7 机器。如果你想做类似的事情,你将不得不处理清理临时文件、检查重复文件等。

foo.cpp,编译成共享库

#include <QtCore/qglobal.h>

extern "C" Q_DECL_EXPORT int foo(int value) 
  return value + 42;

bar.pro,注意没有引用 foo 库

SOURCES += main.cpp
RESOURCES += resources.qrc

ma​​in.cpp

#include <QtCore>
#include <iostream>

int main(int argc, char **argv) 
  QCoreApplication app(argc, argv);

  // Copy resource dll to temporary file.
  QFile::copy(":/lib/Foo.dll", QDir::temp().filePath("Foo.dll"));

  // Load the temporary file as a shared library.
  QLibrary foo_lib(QDir::temp().filePath("Foo.dll"));
  typedef int (*FooDelegate)(int);
  FooDelegate foo = (FooDelegate)foo_lib.resolve("foo");

  if (foo) 
    std::cout << "foo(13) = " << foo(13) << std::endl;
  

【讨论】:

+1。感谢您的回答。但我的问题是 DLL 在目标计算机上不可用......所以我想删除依赖项,将其存储在资源中并在可能的情况下动态加载。此外,用户应该只看到一个没有安装的 .exe 文件... 哦,我明白了。您可能已经想到了这一点,但是您能否获得可以静态链接的库版本?这听起来就像你最终想要实现的目标。 如果您不能静态链接,您可以尝试,在您的 main() 方法中,将 DLL 作为二进制资源加载并将其放在某个特定位置,喜欢系统的临时目录,然后使用QLibrary 从那里加载它。不过,那是一种非常糟糕的代码气味,而且您可能会遇到安全问题。 我认为我可以将其存储为资源而无需创建新文件:) 是否需要?以及如何告诉系统,我的 exe 不依赖该 dll(或者它不会启动:()?.. 我认为你必须创建临时文件——这是系统库加载函数所期望的。因为所有的加载都是在运行时基于魔术字符串进行的,所以没有依赖关系;如果出现问题,您只会遇到严重的崩溃。【参考方案2】:

我只能从 Microsoft 编译器的角度发言...这与其说取决于 QT 想要什么,不如说取决于访问延迟加载的代码和/或数据的时间和地点。

一般来说,您必须告诉链接器DLL 是使用/delayload:[dllname] 选项延迟加载的,并使用delayimp.lib 链接。您可以使用

在 .cpp 文件中添加库

#pragma comment(lib, "delayimp")

这将消除在链接器命令行上指定它的需要。

我不确定 .pro 文件中包含什么来完成将延迟加载开关添加到链接器命令。

有关 Microsoft 文档,请参阅 this link。

【讨论】:

感谢您的回答。但我不知道在 QT 中在哪里写 /delayload:[dllname] ... QT 也返回“忽略杂注注释”。

以上是关于QT 中的延迟 DLL 加载的主要内容,如果未能解决你的问题,请参考以下文章

dll隐式链接延迟加载

WinXP下如何修复DWMAPI.DLL延迟加载依赖?

Windows 中的延迟加载

延迟加载具有相同名称的不同库

怎样可以将DLL编译到EXE文件里

for循环中的QT cpp延迟