从dll启动Qt GUI(在DLLStart函数中)

Hor*_*ter 9 c++ dll qt

我必须从dll公开DLLStart和启动Qt GUI DLLStop.main中的正常(.exe)方法如下:

int main(int argc, char *argv[]) {
    QApplication a(argc, argv); Dialog w;
    w.show();
    return a.exec();
}
Run Code Online (Sandbox Code Playgroud)

问题是阻塞a.exec()调用,因为在dll中DLLStart需要立即返回(见下文).有什么解决方法吗?备注:问题是与" 向动态库添加Qt GUI "共享一些共同点,但它并不完全重复.

/** start module  */
int __stdcall DLLStart(void) {
    .. 
    QApplication qaDll(ac, av); Dialog w;
    w.show();
    qaDll.exec();
    return 0; // never reached
}

/** stop module */
void __stdcall DLLStop(void) { }
Run Code Online (Sandbox Code Playgroud)

Rei*_*ica 15

在Windows上运行的一种方法是QApplication单独启动QThread.它不可移植 - 它不适用于OS X(我正在研究修复).

但是,您不需要单独的线程.如果将代码注入正在运行的应用程序,它已经有一个事件循环.您只需要创建一个全局QApplication对象就可以了.事件循环已在运行,因此您无需调用exec().Qt的窗口与本机事件循环集成,一切都很好.

需要QCoreApplication::processEvents一次电话.它会将当前的应用程序实例集成到windows事件循环中,就是这样.

因此,您的启动代码可能如下所示:

static struct Data {
  int argc = 1;
  char *argv[2] = {strdup("dummy"), {}};
  QApplication app{argc, argv};
  MainWindow win;
} *d;

static void startup() {
  d = new Data;
  d->win.show();
  d->app.processEvents();
}

static void shutdown() {
  delete d;
}
Run Code Online (Sandbox Code Playgroud)

startup()shutdown()应在适当的时候被调用(工艺连接和分离).


老答案如下.这不再完全是最新的.

下面是一个简短的例子,对于一个完整的自包含示例,请参阅我的其他答案.

它不可移植,这就是Qt文档建议反对它的原因.它在Windows上运行得很好.主线程不是魔术 - 不是在Windows上.OS X上的Cocoa在某种程度上是笨拙的,并且显然是不可能的:(.

请注意,如果加载DLL的应用程序已经使用Qt,那么您无需进一步操作.确保使用相同的C++编译器编译DLL,链接到相同的C++运行时,并使用与应用程序使用的二进制兼容的Qt版本.然后,您不需要自己的实例QApplication.要完成一些有用的工作,请显示一个Widget或QObjects使用定时器实例化一些将让他们忙碌的小工具.您也可以使用QMetaObject::invokeMethod(obj, "mySlot", Qt::QueuedConnection)而不是使用计时器:当控制返回到事件循环时,将进行调用.

如果那是不可能的,那么下面是您唯一的选择.据我所知,工作得很好.

请注意,我在这里有点讽刺:如果您是使用DLL的应用程序的作者,则可以可靠地满足前一段中的条件.否则 - 忘了它.

class AppThread : public QThread {
  int & argc;
  char ** argv;
  int result;
  void run() {
    QApplication a(argc, argv);
    Dialog d;
    d.show();
    result = a.exec();
  }
public:
  AppThread(int & argc, char ** argv) : argc(argc), argv(argv) {}
  ~AppThread() { quit(); wait(); }
}

extern "C" int __stdcall DLLStart(void) {
  auto *thread = new AppThread(argc, argv);
  thread->start();
  return 0;
}

extern "C" void __stdcall DLLStop(void) {
  delete qApp->thread();
}
Run Code Online (Sandbox Code Playgroud)