2010-01-27 12 views
22

¿Lo estoy haciendo bien?Usando una DLL basada en Qt en una aplicación que no es Qt

Un cliente mío tiene un grupo en el que estoy desarrollando cosas de servidor-cliente basadas en Qt con muchas cosas divertidas para widgets.

Otro grupo de la empresa desea utilizar una versión empaquetada de las clases de proveedor de datos de cliente basadas en QTcpSocket. (Lo cual hace básicamente lo que suena, proporciona datos del servidor a las pantallas del cliente)

Sin embargo, ese grupo tiene una gran aplicación construida principalmente con MFC, y eso simplemente no va a cambiar pronto. La DLL basada en Qt también carga el retraso para que pueda implementarse sin esta característica en ciertas configuraciones.

Lo tengo funcionando, pero es un poco hacky. Aquí está mi solución en este momento:

El constructor de la clase contenedora DLL llama a QCoreApplication :: instance() para ver si es NULL o no. Si es NULL, se supone que está en una aplicación no Qt, y se crea una instancia QCoreApplication de su propia:

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

A continuación, pondrá en marcha un temporizador ventanas para llamar de vez en cuando 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); 
} 

La devolución de llamada simplemente llama a la función processEvents() utilizando timerID como un puntero a la instancia de clase. SetTimer() dice que cuando HWND es NULL ignora el ID de tiempo, por lo que parece ser perfectamente válido.

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

Luego destruyo la instancia de QCoreApplication como la última cosa en el destructor.

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

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

Si la aplicación host desea medir el tiempo de las llamadas a processEvents() en sí, puede pasar 0 en eventTimerInterval para llamar y blahblah :: processEvents() en sí.

¿Alguna idea de esto? Transferir esa aplicación a Qt no es una opción. No es nuestro

Parece que funciona, pero probablemente haya varias suposiciones que se rompen aquí. ¿Puedo simplemente construir una QCoreApplication con argumentos ficticios como ese? ¿La cola de eventos es segura para operar de esta manera?

No quiero que me explote en la cara más tarde. ¿Pensamientos?

+0

estoy recurriendo a hacer esto por mí mismo. Qt 3 aparentemente tenía soporte para crear dlls de plugins - p. Complementos tipo npapi para navegadores basados ​​en safari de cromo y mozilla. Pero eso parece haber sido eliminado de Qt 4. –

+2

¡Gracias por hacer la pregunta! ¿Sabes si este es el mejor enfoque ahora en 4.8 o hay una mejor manera? En realidad, ejecuto un QThread por separado y creo y ejecuto QCoreApplication allí (global argc y argv). QThread no necesita QCoreApplication, solo algunos mensajes a nivel de sistema, como el temporizador, necesitan el despachador. – dashesy

Respuesta

1

La documentación de Qt para 4.5.2 dice que los argumentos para QCoreApplication necesitan tener una vida útil tan larga como el objeto de la aplicación, por lo que no debería usar variables locales.

Aparte de esa pequeña cosa:

estoy luchando con el mismo problema, y ​​todo parece funcionar para mí también. Sin embargo, recomendaría ser muy cuidadoso en el momento de la descarga/salida, ya que si está utilizando el bucle de eventos de otra aplicación y ese bucle de eventos se detiene antes de que se descargue su biblioteca, todo tipo de desagradables problemas pueden ocurrir cuando intenta cerrar() sockets y eliminar QObjects.

6

Al estudiar el código Qt, parece que QCoreApplication es necesaria para enviar mensajes en todo el sistema, como los eventos del temporizador.Cosas como signal/slots e incluso QThreads no dependen de él a menos que estén relacionados con esos mensajes de todo el sistema. Aquí es cómo lo hago en una biblioteca compartida (de forma cruzada usando Qt) y realmente llamo al exec, porque processEvents() solo no procesa todo.

Tengo un espacio de nombres global:

// Private Qt application 
namespace QAppPriv 
{ 
    static int argc = 1; 
    static char * argv[] = {"sharedlib.app", NULL}; 
    static QCoreApplication * pApp = NULL; 
    static QThread * pThread = NULL; 
}; 

tengo un métodoopenapp en un QObject (es decir moc'ed) así:

// Initialize the app 
if (QAppPriv::pThread == NULL) 
{ 
    // Separate thread for application thread 
    QAppPriv::pThread = new QThread(); 
    // Direct connection is mandatory 
    connect(QAppPriv::pThread, SIGNAL(started()), this, SLOT(OnExec()), Qt::DirectConnection); 
    QAppPriv::pThread->start(); 
} 

Y aquí es OnExec ranura:

if (QCoreApplication::instance() == NULL) 
{ 
    QAppPriv::pApp = new QCoreApplication(QAppPriv::argc, QAppPriv::argv); 
    QAppPriv::pApp->exec(); 
    if (QAppPriv::pApp) 
     delete QAppPriv::pApp; 
} 

Hasta ahora parece estar funcionando bien, no estoy seguro si necesito eliminar la aplicación al final, actualizaré mi respuesta si encuentro algo.

+0

dashey - ¿cómo te funcionó? – ExpatEgghead

+0

@ExpatEgghead Funciona bastante bien en realidad (https://github.com/dashesy/CereLink) – dashesy

+0

Y finalmente funcionó para mí también. Tiempo de Votación. – ExpatEgghead

3

Creo que las clases de "Migración de MFC a Qt" pueden ayudarlo.

Enlace: http://doc.qt.nokia.com/solutions/4/qtwinmigrate/winmigrate-walkthrough.html

+0

Lo siento, pensé que la publicación era de este año ... – Gojir4

+2

No hay necesidad de disculparse. Las respuestas son siempre bienvenidas, no importa si la pregunta es antigua. Sin embargo, sería mejor evitar [vincular solo respuestas] (http://meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers). Por lo que es posible que desee mejorar su respuesta. No solo copie y pegue el contenido. :) – Bart

+0

Esta es la respuesta correcta para ejecutar widgets Qt o Dlls en una aplicación MFC. – Matthew

Cuestiones relacionadas