tags:

views:

351

answers:

1

Am I doing it right?

A client of mine has a group where I'm developing Qt-based client-server stuff with a lot of fun widget stuff and sockets.

Another group within the company wants to use a wrapped version of the QTcpSocket-based client data provider classes. (Which does basically what it sounds like, provides data from the server to the client displays)

However, that group has a huge application built mostly with MFC, and that is simply not going to change any time soon. The Qt-based DLL is also delay-loading so that it can be deployed without this feature in certain configurations.

I've got it working, but it's a little hacky. Here's my solution at the moment:

The DLL wrapper class constructor calls QCoreApplication::instance() to see if it's NULL or not. If it's NULL, it assumes it's in a non-Qt app, and creates a QCoreApplication instance of it's own:

if (QCoreApplication::instance() == NULL)
{
    int argc = 1;
    char* argv[] = { "dummy.exe", NULL };
    d->_app = new QCoreApplication(argc, argv);  // safe?
}
else
    d->_app = NULL;

It then will set up a windows timer to occasionally call 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);
}

The callback simply calls the processEvents() function using the timerID as a pointer to the class instance. The SetTimer() docs say when HWND is NULL it ignores the timerID, so this appears to be perfectly valid.

VOID CALLBACK BLAHBLAH_TimerCallback(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
    ((BLAHBLAH*)idEvent)->processEvents(); // basically just calls d->_app->processEvents();
}

I then destroy the QCoreApplication instance as the very last thing in the destructor.

BLAHBLAH::~BLAHBLAH()
{
    .. other stuff

   QCoreApplication* app = d->_app;
   d->_app = NULL;
   delete d;
   if (app != NULL)
       delete app;
}

If the hosting application wishes to time the calls to processEvents() itself, it can pass 0 in for eventTimerInterval and call BLAHBLAH::processEvents() itself.

Any thoughts on this? Porting that app to Qt is not an option. It's not ours.

It appears to work, but there are probably several assumptions being broken here. Can I just construct a QCoreApplication with dummy arguments like that? Is the event queue safe to operate in this manner?

I don't want this blowing up in my face later. Thoughts?

A: 

The Qt Documentation for 4.5.2 says that the arguments to QCoreApplication need to have lifetimes as long as the application object - so you shouldn't really use local variables.

Apart from that little thing:

I'm grappling with the same problem, and everything seems to work for me too. I would recommend being very careful at unload / exit time, however, since if you're using the event loop from another application and that event loop is stopped before your library is unloaded then all sorts of crashy nastiness can happen when you try to close() sockets and delete QObjects.

Autopulated