假设我有一个包含我的程序的文件夹,还有一个带有外部库的文件夹。
bin
myprog.exe
etc
lib.dll
sublib.dll
在我的情况下,我想从主程序lib.dll
加载myprog.exe
。问题是lib.dll
与sublib.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.dll
和sublib.dll
都放在bin
目录中,它可以正常运行。但那不是我想做的。
我试过
a.addLibraryPath("C:/etc");
但这不起作用。
据我所知QCoreApplication::addLibraryPath()
为Qt程序设置路径,而不是系统范围设置。因此,在这种情况下,lib.dll
仍然无法找到sublib.dll
,尽管它位于同一目录中。
所以我的问题 - 如果这个库有自己的依赖项,如何在Qt程序中加载外部共享库?
答案 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
,你不应该在任何现代安装程序中写任何东西(也不要在任何子文件夹中)。