10

I have to start a Qt GUI from a dll exposing DLLStart and DLLStop. The normal (.exe) approach in main is as follows:

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

The problem is the blocking a.exec() call, since in the dll DLLStart needs to return immediately (see below). Any workaround for this? Remark: The question is sharing some common ground with " Adding a Qt GUI to a Dynamic Library ", but it is no exact duplicate.

/** 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) { }
4

1 に答える 1

16

Windowsで機能する1つの方法QApplicationは、別ので開始することQThreadです。移植性はありません-OSXでは動作しません(私は修正を研究しています)。

ただし、別のスレッドは必要ありません。実行中のアプリケーションにコードを挿入すると、すでにイベントループが発生しています。グローバルオブジェクトを作成するだけで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のCocoaはある意味不器用で、それを不可能にしているようです:(。

DLLをロードするアプリケーションがすでにQtを使用している場合は、これ以上何もする必要がないことに注意してください。DLLを同じC++コンパイラでコンパイルし、同じC ++ランタイムに対してリンクし、アプリケーションで使用されているものとバイナリ互換のバージョンのQtを使用していることを確認してください。その場合、の独自のインスタンスは必要ありませんQApplication。いくつかの便利な作業を行うには、ウィジェットを表示するか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();
}
于 2012-06-15T19:02:18.447 に答える