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();
}