【发布时间】:2019-07-07 03:06:00
【问题描述】:
要求:none-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 加载库,但是,我使用 Win32 API 加载库的事件也失败了。
#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!";
}
}
【问题讨论】:
-
新线程好像没有运行,你看看:stackoverflow.com/questions/54702090/…
-
好像我不能在静态变量初始化块中创建线程,因为这部分是在dllMain函数中运行的,在dllMain中创建线程会导致死锁,但是,有什么办法可以打破这个规则?
-
不要在
DllMain中创建线程 - 请参阅 MSDN。 -
@DDrmmr 感谢您的回复 :) 是的,在“dllMain”中创建线程是个坏主意,它会导致我的应用程序阻塞。我在 dllMain 中使用线程找到了其他人的演示,效果很好。不是在 C++ 中,而是在 Delphi 中。睡眠 1 秒,UI 的东西开始,但在 C++ 中,失败:(
-
@vg0x00 我不明白你的第 4 点。你能解释一下吗?