簡體   English   中英

從dll啟動Qt GUI(在DLLStart函數中)

[英]Starting Qt GUI from dll (in DLLStart function)

我必須從暴露DLLStartDLLStop的dll啟動Qt GUI。 main中的常規(.exe)方法如下:

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

問題在於阻塞了a.exec()調用,因為在DLLStart中, 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) { }

在Windows上工作的一種方法是在單獨的QThread啟動QApplication 它不是便攜式的-在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;
}

應該在適當的時間(在進程附加和分離時)調用startup()shutdown() )。


舊答案如下。 這不再是最新的了。

下面是一個簡短的示例,有關完整的獨立示例,請參見我的其他答案

它不是可移植的,這就是Qt文檔建議不要這樣做的原因。 在Windows上可以正常使用。 主線程不是魔術,不是Windows。 OS X上的可可在某種程度上很笨拙,並且使它變得不可能,顯然:(。

請注意,如果加載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();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM