Вот рабочий пример.Протестировано с Qt 5.12, MSVC2017 и MinGW.
// main.cpp
int main(int argc, char *argv[])
{
run_mylib_t *f= nullptr;
HMODULE lib = LoadLibraryA("..\\mylib\\debug\\mylib.dll");
if (!lib) {
qDebug() << "Failed to load library;";
return -1;
}
f = reinterpret_cast<run_mylib_t *>(GetProcAddress(lib, "run_mylib"));
if (!f) {
qDebug() << "Failed to get function";
return -1;
}
f(argc, argv);
return 0;
}
// mylib.h
extern "C" MYLIBSHARED_EXPORT int run_mylib(int argc, char *argv[]);
using run_mylib_t = int(int, char *[]);
// mylib.cpp
int loop(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
int run_mylib(int argc, char *argv[])
{
auto lambda = [argc, argv]() {loop(argc, argv); };
std::thread thread(lambda);
thread.join();
return 0;
}
Обратите внимание, что если вы используете функцию Qt до создания потока, Qt обнаружит, что его нет в основном потоке, и процесс завершится сбоем.Вот почему я не использую QLibrary
.
Этот вариант использования не поддерживается Qt.Поэтому, если вы заставите его работать сейчас, вы не гарантируете, что он будет работать в будущем.
Вы не можете загружать одновременно 2 dll, как это.
В зависимости от того, что вы делаете вВаше основное приложение, может случиться так, что некоторые функции Qt не работают должным образом.Например, может случиться, что Qt ожидает сообщения от Windows, но никогда не получит их, потому что они будут обрабатываться реальным основным потоком.
О DllMain
Из документации Windows:
Предупреждение
Существуют значительные ограничения на то, что вы можете безопасно делать в точке входа DLL.См. Общие рекомендации для конкретных API-интерфейсов Windows, которые небезопасны для вызова в DllMain.Если вам нужно что-то кроме самой простой инициализации, сделайте это в функции инициализации для DLL.Вы можете требовать, чтобы приложения вызывали функцию инициализации после запуска DllMain и до того, как они вызовут любые другие функции в DLL.
- https://docs.microsoft.com/en-us/windows/desktop/dlls/dllmain
и Dynamic-Link Library BestПрактика:
Никогда не выполняйте следующие задачи из DllMain:
- Вызовите LoadLibrary или LoadLibraryEx (прямо или косвенно).Это может вызвать тупик или сбой.
- Вызовите GetStringTypeA, GetStringTypeEx или GetStringTypeW (прямо или косвенно).Это может вызвать тупик или сбой.
- Синхронизация с другими потоками.Это может вызвать взаимоблокировку.
- Получить объект синхронизации, принадлежащий коду, который ожидает получения блокировки загрузчика.Это может вызвать взаимоблокировку.
- Инициализировать потоки COM с помощью CoInitializeEx.При определенных условиях эта функция может вызывать LoadLibraryEx.
- Вызывать функции реестра.Эти функции реализованы в Advapi32.dll.Если Advapi32.dll не инициализируется до вашей DLL, DLL может получить доступ к неинициализированной памяти и вызвать сбой процесса.
- Вызовите CreateProcess.Создание процесса может загрузить другую DLL.
- Вызов ExitThread.Выход из потока во время отсоединения DLL может привести к повторному получению блокировки загрузчика, вызывая тупик или сбой.
- Вызов CreateThread.Создание потока может работать, если вы не синхронизируете его с другими потоками, но это рискованно.
- Создание именованного канала или другого именованного объекта (только в Windows 2000).В Windows 2000 именованные объекты предоставляются библиотекой служб терминалов.Если эта DLL не инициализирована, вызовы DLL могут вызвать сбой процесса.
- Используйте функцию управления памятью из динамического C-Run-Time (CRT).Если библиотека CRT не инициализирована, вызов этих функций может привести к сбою процесса.
- Вызов функций в User32.dll или Gdi32.dll.Некоторые функции загружают другую DLL, которая не может быть инициализирована.
- Использовать управляемый код.
- https://docs.microsoft.com/en-us/windows/desktop/dlls/dynamic-link-library-best-practices
Из этого я могу сказать,Если вы не сможете создать QApplication
и запустить приложение Qt из DllMain
по крайней мере по следующим причинам:
- Qt будет загружать плагины (по крайней мере
qwindows.dll
) используя LoadLibrary
.Если вы используете какую-либо базу данных аудио или изображений или sql, Qt также попытается загрузить соответствующие плагины (например, qjpeg.dll
). - Qt также может попытаться получить доступ к реестру, в частности, если вы используете
QSettings
с собственным форматом. - Qt может создавать потоки.В частности, если вы используете сеть или Qt Quick.
- Qt будет использовать функции управления памятью, такие как
malloc
или free
.