2009-11-23 3 views
4

J'écris une DLL qui est utilisée comme un plugin par une autre application et qui souhaite tirer parti des capacités de Qt.
Toutes les classes sont configurées, compilées et exécutées, mais aucun signal n'est émis. Il semble donc qu'il n'y a pas de QEventLoop.Qt problèmes de boucle d'événements de la bibliothèque

Tentative 1:
J'ai modifié ma classe principale sous-classe QThread au lieu de QObject, et dans la course() créer un QEventLoop, connecter tous les signaux/slots et exec le fil.
Mais cela échoue en disant que vous ne pouvez pas avoir un QEventLoop sans QApplication.

Essai 2:
I modifié la classe principale (sous-classer encore le QThraed) pour instancier une place QCoreApplication, connecter tous les signaux/slots, puis exec l'application.
Avertit que QApplication n'a pas été créé dans le thread principal() et n'émettra toujours pas de signaux.

Je ne sais pas quoi faire ici. Je ne peux évidemment pas créer un QCoreApplication dans l'application qui utilisera mon plugin, et je ne peux pas émettre de signaux sans un.

J'ai inclus une application de test simple (et horriblement écrit) qui devrait illustrer mon problème:

Toute aide serait appréciée!

main.cpp:

#include <iostream> 
#include "ThreadThing.h" 
using namespace std; 
int main(int argc, char *argv[]) 
{ 
    cout << "Main: " << 1 << endl; 
    ThreadThing thing1; 
    cout << "Main: " << 2 << endl; 
    thing1.testStart(); 
    cout << "Main: " << 3 << endl; 
    thing1.testEnd(); 
    cout << "Main: " << 4 << endl; 
    thing1.wait(-1); 
    cout << "Main: " << 5 << endl; 
    return 0; 
} 

ThreadThing.h:

#ifndef THREADTHING_H 
#define THREADTHING_H 
#include <QThread> 
class ThreadThing : public QThread 
{ 
    Q_OBJECT 
public: 
    ThreadThing(); 
    virtual void run(); 
    void testStart(); 
    void testEnd(); 
public slots: 
    void testSlot(); 
signals: 
    void testSignal(); 
}; 
#endif//THREADTHING_H 

ThreadThing.cpp:

#include "ThreadThing.h" 
#include <iostream> 
#include <QCoreApplication> 

using namespace std; 

ThreadThing::ThreadThing() 
{ 
    cout << "Constructor: " << 1 << endl; 
    this->start(); 
    cout << "Constructor: " << 2 << endl; 
} 

void ThreadThing::run() 
{ 
    cout << "Run: " << 1 << endl; 
    int i = 0; 
    cout << "Run: " << 2 << endl; 
    QCoreApplication* t = new QCoreApplication(i, 0); 
    cout << "Run: " << 3 << endl; 
    connect(this, SIGNAL(testSignal()), this, SLOT(testSlot()), Qt::QueuedConnection); 
    cout << "Run: " << 4 << endl; 
    t->exec(); 
    cout << "Run: " << 5 << endl; 
} 

void ThreadThing::testStart() 
{ 
    cout << "TestStart: " << 1 << endl; 
    emit testSignal(); 
    cout << "TestStart: " << 2 << endl; 
} 

void ThreadThing::testEnd() 
{ 
    cout << "TestEnd: " << 1 << endl; 
    this->quit(); 
    cout << "TestEnd: " << 1 << endl; 
} 

void ThreadThing::testSlot() 
{ 
    cout << "TEST WORKED" << endl; 
} 

sortie:

Main: 1 
Constructor: 1 
Constructor: 2 
Main: 2 
TestStart: 1 
TestStart: 2 
Main: 3 
TestEnd: 1 
TestEnd: 1 
Main: 4 
Run: 1 
Run: 2 
WARNING: QApplication was not created in the main() thread. 
Run: 3 
Run: 4 

Répondre

5

Vous avez pour créer un QCoreApplication ou QApplication et vous avez pour le faire dans le fil principal. Cela ne veut pas dire que vous ne pouvez pas mettre le code pour cela dans votre plugin ... à moins que l'application n'exécute toujours chaque plugin dans son propre thread. Si l'application est en faisant cela, vous pouvez essayer de vous connecter à la boucle d'événements native utilisée par l'application, et faire en sorte qu'elle appelle une fonction dans votre plugin dans le thread principal.

+0

Malheureusement, je ne peux pas toucher quoi que ce soit dans l'application principale qui est l'aide de mon plug-in, et je reçois seulement d'exécuter du code lorsqu'il appelle un nombre limité de fonctions (crochets DLL et un couple de fonctions enregistrées). En plus de cela, je ne sais pas si ma DLL est appelée par le thread principal ou par un plugin. La pire partie est que même si je suis dans l'espace de discussion principal, je ne peux pas appeler l'instruction de blocage exec() quand elle me passe le contrôle car je dois retourner pour que l'application principale fonctionne. Donc, il n'y a absolument aucun moyen que je puisse avoir une Qt lib pour une application tierce non-Qt? – Marc

+0

Si vous ne pouvez pas trouver un moyen sûr d'instancier une application QCoreApplication ou QApplication, vous ne pouvez pas utiliser la plupart de Qt. Je serais surpris si vous ne pouvez pas trouver une solution, bien que - après tout, vous avez un plugin C++, qui peut exécuter du code arbitraire dans le processus de demande. Il y aura un moyen de le faire fonctionner. – rohanpm

1

J'ai réussi à créer une QCoreApplication et à l'exécuter sur un thread d'arrière-plan. Ceci est pas une implémentation standard, mais peut fonctionner pour la fonctionnalité de signal/slot simple. Je l'ai fait pour une application iOS native avec une grande base de code Qt ancienne.

//I really don't do anything but run on a background thread 
class MyQtAppForBackgroundThread : public QCoreApplication 
{ 
    Q_OBJECT 
    ... 
} 

//iOS specific code here... 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^(void){ 
     // This spawns a QCoreApplication on a background thread in an attempt to create something that can 
     // queue signals across threads 
     qtApp = new MyQtAppForBackgroundThread(smArgc, smArgv); 
     qtApp->exec(); 

    }); 

Les signaux déclenchés sur le même thread où ils étaient connectés seront interceptés. Pour attraper des signaux sur différents threads, vous devez créer et interroger un QEventLoop sur le thread où les signaux ont été créés.

//Fire me periodically on the thread the signals and slots were connected 
QEventLoop loop; 
loop.processEvents(QEventLoop::ExcludeUserInputEvents, 500); 
Questions connexes