Reputation: 12874
Assume, I have a folder with my program and also another folder with external library.
bin
myprog.exe
etc
lib.dll
sublib.dll
In my case I want to load the lib.dll
from my main program myprog.exe
. The problem is that lib.dll
linked with sublib.dll
.
So I try to do that in this way:
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();
After running the app I get the error:
cannot load library lib.dll the specified module could not be found
If I put both lib.dll
and sublib.dll
inside bin
directory it works without error. But that is not I want to do.
I've tried
a.addLibraryPath("C:/etc");
but that doesn't work.
As I understand QCoreApplication::addLibraryPath()
sets path for Qt program, not as system wide setting. So, in this case, lib.dll
still can't find sublib.dll
although it locates in same directory.
So my question - how can I load external shared library inside Qt program in case that this library has its own dependencies?
Upvotes: 1
Views: 8461
Reputation: 98525
Nothing prevents you from explicitly preloading the libraries that lib.dll
depends on. Once pre-loaded, they're ready for use by any library that you'll subsequently open. After all, you know where they are so it's a simple matter to iterate them and attempt to load them. Due to possible dependencies between these libraries, you have to keep loading them until there's no more progress:
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;
}
}
It's either that or to use a PE library of your choice to build the dependency tree yourself and only open the necessary libraries, in dependency order.
Side note: you don't own C:\Windows
and you should never write anything there (nor in any subfolder) in any sort of a modern installer.
Upvotes: 2
Reputation: 8718
That is Windows issue. The DLL will be looked at the current process directory and then in the system PATH. The code that is contained in some C:\etc\lib.dll
is behaving in its own process and unless very specific logic implemented will behave according to the system rule.
Please refer to MSDN article Dynamic-Link Library Search Order for details. If the source code for that lib.dll is available, it makes sense to examine LoadLibrary call. If there is no specific path provided then:
The first directory searched is the directory containing the image file used to create the calling process (for more information, see the CreateProcess function). Doing this allows private dynamic-link library (DLL) files associated with a process to be found without adding the process's installed directory to the PATH environment variable. If a relative path is specified, the entire relative path is appended to every token in the DLL search path list. To load a module from a relative path without searching any other path, use GetFullPathName to get a nonrelative path and call LoadLibrary with the nonrelative path. For more information on the DLL search order, see Dynamic-Link Library Search Order.
Upvotes: 3