Est-ce que je le fais bien ?
Un de mes clients a un groupe dans lequel je développe des applications client-serveur basées sur Qt, avec beaucoup de widgets amusants et de sockets.
Un autre groupe au sein de l'entreprise souhaite utiliser une version enveloppée des classes de fournisseur de données client basées sur QTcpSocket. (qui fait essentiellement ce qu'il semble, fournir des données du serveur aux écrans clients).
Cependant, ce groupe possède une énorme application construite principalement avec MFC, et cela n'est pas prêt de changer. La DLL basée sur Qt est également à chargement différé afin qu'elle puisse être déployée sans cette fonctionnalité dans certaines configurations.
J'ai réussi à le faire fonctionner, mais c'est un peu compliqué. Voici ma solution pour le moment :
Le constructeur de la classe wrapper DLL appelle QCoreApplication::instance() pour voir si elle est NULL ou non. S'il est NULL, il suppose qu'il est dans une application non-Qt, et crée sa propre instance QCoreApplication :
if (QCoreApplication::instance() == NULL)
{
int argc = 1;
char* argv[] = { "dummy.exe", NULL };
d->_app = new QCoreApplication(argc, argv); // safe?
}
else
d->_app = NULL;
Il mettra ensuite en place un timer Windows pour appeler occasionnellement processEvents() :
if (eventTimerInterval > 0)
{
// STATE: start a timer to occasionally process the Qt events in the event queue
SetTimer(NULL, (UINT_PTR)this, eventTimerInterval, CDatabaseLayer_TimerCallback);
}
Le callback appelle simplement la fonction processEvents() en utilisant le timerID comme pointeur vers l'instance de la classe. La documentation de SetTimer() indique que lorsque le HWND est NULL, il ignore le timerID, ce qui semble donc parfaitement valable.
VOID CALLBACK BLAHBLAH_TimerCallback(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
((BLAHBLAH*)idEvent)->processEvents(); // basically just calls d->_app->processEvents();
}
Je détruis ensuite l'instance de QCoreApplication en toute dernière chose dans le destructeur.
BLAHBLAH::~BLAHBLAH()
{
.. other stuff
QCoreApplication* app = d->_app;
d->_app = NULL;
delete d;
if (app != NULL)
delete app;
}
Si l'application hôte souhaite chronométrer elle-même les appels à processEvents(), elle peut passer 0 pour eventTimerInterval et appeler BLAHBLAH::processEvents() elle-même.
Des idées à ce sujet ? Porter cette application sur Qt n'est pas une option. Ce n'est pas la nôtre.
Cela semble fonctionner, mais il y a probablement plusieurs hypothèses qui sont brisées ici. Puis-je simplement construire une QCoreApplication avec des arguments factices comme ça ? La file d'attente d'événements peut-elle fonctionner de cette manière ?
Je ne veux pas que ça m'explose à la figure plus tard. Tu en penses quoi ?