在Windows中的Qt中加载外部dll

时间:2016-01-06 03:47:04

标签: c++ windows qt dll

假设我有一个包含我的程序的文件夹,还有一个带有外部库的文件夹。

bin
    myprog.exe
etc
    lib.dll
    sublib.dll

在我的情况下,我想从主程序lib.dll加载myprog.exe。问题是lib.dllsublib.dll相关联。

所以我试着这样做:

QCoreApplication a(argc, argv);
QLibrary lib;
QString path = "C:/etc/lib.dll";
a.addLibraryPath(path);

if(QLibrary::isLibrary(path)) {
    lib.setFileName(path);
    lib.load();
    if(lib.isLoaded())
        qDebug() << "Ok\n";
    else
        qDebug() << "Error " << lib.errorString() << "\n";
} else
    qDebug() << "Not a library\n";
return a.exec(); 

运行应用程序后,我收到错误:

  

无法加载库lib.dll无法找到指定的模块

如果我将lib.dllsublib.dll都放在bin目录中,它可以正常运行。但那不是我想做的。

我试过

a.addLibraryPath("C:/etc");

但这不起作用。 据我所知QCoreApplication::addLibraryPath()为Qt程序设置路径,而不是系统范围设置。因此,在这种情况下,lib.dll仍然无法找到sublib.dll,尽管它位于同一目录中。

所以我的问题 - 如果这个库有自己的依赖项,如何在Qt程序中加载外部共享库?

2 个答案:

答案 0 :(得分:2)

那是Windows问题。 DLL将查看当前进程目录,然后查看系统PATH。某些C:\etc\lib.dll中包含的代码在其自己的进程中运行,除非实现的非常具体的逻辑将根据系统规则运行。

有关详细信息,请参阅MSDN文章Dynamic-Link Library Search Order。如果该lib.dll的源代码可用,则检查LoadLibrary调用是有意义的。如果没有提供特定路径,则:

  

搜索的第一个目录是包含图像的目录   用于创建调用进程的文件(有关更多信息,请参阅   CreateProcess函数)。这样做可以实现私有动态链接   与没有找到的进程关联的库(DLL)文件   将进程的已安装目录添加到PATH环境中   变量。如果指定了相对路径,则整个相对路径为   附加到DLL搜索路径列表中的每个标记。加载模块   从没有搜索任何其他路径的相对路径,使用   GetFullPathName获取非相对路径并调用LoadLibrary   非相对路径。有关DLL搜索顺序的更多信息,   请参阅动态链接库搜索顺序。

答案 1 :(得分:1)

没有什么能阻止您明确预加载lib.dll依赖的库。预加载后,它们随时可供您随后打开的任何库使用。毕竟,你知道它们在哪里,所以迭代它们并尝试加载它们是一件简单的事情。由于这些库之间可能存在依赖关系,因此必须继续加载它们,直到不再有进展:

   QString path;
   QSet<QString> libraries;
   QDirIterator it{path, {"*.dll"}};
   while (it.hasNext())
     libraries << it.next();
   bool progress = true;
   while (progress) {
     progress = false;
     for (auto i = libraries.begin(); i != libraries.end();) {
       QLibrary lib{*i};
       if (lib.load()) {
         progress = true;
         i = libraries.erase(i);
       } else
         ++i;
      }
   }

或者使用您选择的PE库来自己构建依赖树,并且只按依赖顺序打开必要的库。

附注:你没有C:\Windows,你不应该在任何现代安装程序中写任何东西(也不要在任何子文件夹中)。

相关问题