要求:Qt 小部件在 Qt 共享库加载时显示,对于非 Qt应用程序。
经过一些网络搜索,我发现:
所有 Qt 小部件都必须存在于“主线程”中,“主线程”是 Qt 对象创建的第一个线程。因此,创建一个非 Qt 线程(std::thread),然后在该线程中创建 QApplication 和其他一些小部件应该可以工作,但不能。
在创建 QApplication 之前,不要在该非 Qt 线程中创建任何 Qt 相关对象或调用任何 Qt 相关静态方法。
线程解决方案不适用于 Mac OS,我的目标平台仅为 Windows,所以没关系。
就我而言,如果应用程序加载我的 Qt 库,并调用显示小部件的方法,它就可以工作。但由于某种原因,调用者无法手动调用我的 lib 方法。
如果宿主应用程序(加载共享库的应用程序)是 Qt 应用程序,您应该调用 QApplication::processEvents(),而不是 QApplication::exec()。就我而言,我应该在该线程中调用 QApplication::exec() 。
源代码在这里:
- dll主要版本:
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
auto t = std::thread([]() {
// setCodecForLocale is in the same thread,
// call it before QApplication created should be OK.
QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK"));
int i = 0;
int argc = 0;
QApplication app(argc, 0);
auto dialogLogin = new DialogLogin(); // custom widget
dialogLogin->setModal(true);
dialogLogin->show();
app.exec(); // app.processEvents() not work, too.
});
t.join(); // wait for thread ends in dllMain should be BAD, test only
}
return true;
}
- 简单 C++ 静态类版本
class LibExecutor {
public:
LibExecutor()
{
auto t = std::thread([]() {
QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK"));
int argc = 0;
QApplication app(argc, 0);
auto dialogLogin = new DialogLogin();
dialogLogin->setModal(true);
dialogLogin->show();
app.exec();
});
t.join();
}
};
static LibExecutor libExecutor;
两个版本都成功调用小部件初始化内容,但小部件未显示。
这是我使用 Qt 加载 lib 进行测试的方法,但是,我使用 Win32 API 加载 lib 的事件也失败了。
#include "mainwindow.h"
#include <QApplication>
#include <QLibrary>
int main(int argc, char* argv[])
{
QLibrary lib("F:/lib_location/lib_name.dll");
if (lib.load()) {
qDebug() << "load ok!";
} else {
qDebug() << "load error!";
}
}