Eine Möglichkeit, unter Windows funktioniert, ist QApplication
in einem separaten QThread
zu starten. Es ist nicht portierbar - unter OS X funktioniert es nicht (ich forsche nach einer Lösung).
Sie benötigen jedoch keinen separaten Thread. Wenn Sie Ihren Code in eine laufende Anwendung injizieren, hat er bereits eine Ereignisschleife. Sie müssen nur ein globales Objekt QApplication
erstellen und fertig. Die Ereignisschleife wird bereits ausgeführt. Sie müssen also nicht exec()
anrufen. Qt's Fenster integrieren sich in die native Event-Schleife, und an dieser Front ist alles gut.
Sie do need einmal anrufen QCoreApplication::processEvents
. Es wird die aktuelle Anwendungsinstanz in die Windows-Ereignisschleife integrieren, und das war's.
So Ihr Startcode könnte wie folgt aussehen:
int * argc = nullptr;
char ** argv = nullptr;
QApplication * app = nullptr;
MainWindow * win = nullptr;
static void startup() {
argc = new int(1);
argv = new char*[1];
argv[0] = strdup("dummy");
auto app = new QApplication(*argc, argv);
auto w = new MainWindow;
w->show();
app->processEvents();
}
static void shutdown()
{
delete win;
delete app;
free argv[0];
delete [] argv;
delete argc;
}
Die startup()
und shutdown()
soll (auf Prozess befestigen und lösen) zu geeigneten Zeitpunkt aufgerufen werden.
Alte Antwort folgt. Dies ist nicht mehr ganz auf dem neuesten Stand.
Ein kurzes Beispiel ist unten, für ein komplettes in sich abgeschlossenes Beispiel siehe meine other answer.
Es ist nicht tragbar und deshalb rät die Qt-Dokumentation davon ab. Es funktioniert gut unter Windows. Der Hauptthread ist keine Magie - nicht unter Windows. Cocoa auf OS X ist in einer Weise ungeschickt und macht es unmöglich, scheinbar :(.
Beachten Sie, dass, wenn die Anwendung, die die DLL lädt bereits verwendet Qt, dann nichts weiter zu tun. Stellen Sie sicher, dass Sie Ihre DLL kompilieren derselbe C++ - Compiler, Verknüpfung mit der gleichen C++ - Laufzeit und Verwendung einer Version von Qt, die binär mit der von der Anwendung verwendeten Version kompatibel ist Sie brauchen dann keine eigene Instanz von QApplication
Um eine nützliche Arbeit zu erledigen, zeigen Sie ein Widget an oder einige QObjects
mit Timer instanziiert, die sie beschäftigt bekommen Sie auch QMetaObject::invokeMethod(obj, "mySlot", Qt::QueuedConnection)
statt mit Timer verwenden können:.. der Anruf, wenn die Steuerung kehrt zu der Ereignisschleife gemacht werden
Wenn das nicht möglich ist, dann unter das ist Ihre einzige Option, Wo Es geht mir gut, soweit ich das beurteilen kann.
Beachten Sie, dass ich hier ein wenig sarkastisch bin: Die Bedingungen im vorherigen Absatz werden möglicherweise zuverlässig erfüllt, wenn Sie der Autor der Anwendung sind, die die DLL verwendet. Sonst - vergiss es.
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_) {}
}
int __stdcall DLLStart(void) {
AppThread * thread = new AppThread(argc, argv);
thread->start();
return 0;
}
void __stdcall DLLStop(void) {
qApp->thread()->quit();
qApp->thread()->wait();
}
Weiß nicht. Ich kann Ihnen nur vorschlagen, dass Sie sich window_qt.cpp im opencv.org-Code ansehen. Es verwendet Qt, um ein einzelnes Fenster mit seiner eigenen Ereignisschleife als Teil einer Nicht-Qt-Bibliothek anzuzeigen. –
Wird 'DllStart' von' DllMain' aufgerufen? Oder vom anrufenden Prozess angerufen? – Synxis
@MB ein Hinweis, wo im Rep (http://code.opencv.org/projects/opencv/repository) diese Datei befindet. Suche findet es nicht, wird eine Beute darin haben. –