2010-01-27 14 views
22

Sto facendo bene?Utilizzo di una DLL basata su Qt in un'applicazione non-Qt

Un mio cliente ha un gruppo in cui sto sviluppando roba client-server basata su Qt con un sacco di cose e prese di widget divertenti.

Un altro gruppo all'interno dell'azienda desidera utilizzare una versione compressa delle classi del fornitore di dati client basate su QTcpSocket. (Che in pratica suona come funziona, fornisce i dati dal server ai display client)

Tuttavia, quel gruppo ha un'enorme applicazione costruita principalmente con MFC e che semplicemente non cambierà molto presto. La DLL basata su Qt è anche in fase di caricamento in ritardo in modo che possa essere distribuita senza questa funzionalità in determinate configurazioni.

Ho funzionato, ma è un po 'hacky. Ecco la mia soluzione al momento:

Il costruttore della classe wrapper DLL chiama QCoreApplication :: instance() per vedere se è NULL o no. Se è NULL, si presuppone che sia in un'applicazione non di Qt, e crea un'istanza QCoreApplication di essa la propria:

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

E poi istituirà un timer finestre di chiamare di tanto in tanto 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); 
} 

Il callback chiama semplicemente la funzione processEvents() utilizzando il timerID come puntatore all'istanza della classe. I documenti SetTimer() dicono che quando HWND è NULL ignora il timerID, quindi questo sembra essere perfettamente valido.

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

Quindi ho eliminato l'istanza QCoreApplication come l'ultima cosa nel distruttore.

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

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

Se l'applicazione di hosting vuole per tempo le chiamate a processEvents() in sé, può passare 0 a eventTimerInterval e chiamare blahblah :: processEvents() stesso.

Qualche idea su questo? Portare l'app su Qt non è un'opzione. Non è nostro.

Sembra funzionare, ma ci sono probabilmente diverse supposizioni in corso. Posso semplicemente costruire una QCoreApplication con argomenti fittizi del genere? La coda degli eventi è sicura per operare in questo modo?

Non voglio che questo mi esploda in faccia dopo. Pensieri?

+0

sto ricorrere a fare questo io stesso. Qt 3 apparentemente aveva il supporto per la creazione di plugin dlls - ad es. plugin di tipo npapi per browser Chrome e browser basati su Mozilla. Ma sembra che sia stato lasciato cadere da Qt 4. –

+2

Grazie per aver fatto la domanda! sai se questo è l'approccio migliore ora in 4.8, o c'è un modo migliore. In realtà eseguo un QThread separato e creo ed eseguo QCoreApplication lì (globale argc e argv). QThread non ha bisogno di QCoreApplication, solo alcuni messaggi a livello di sistema come il timer hanno bisogno del dispatcher. – dashesy

risposta

1

La documentazione Qt per 4.5.2 afferma che gli argomenti di QCoreApplication devono avere una durata purché l'oggetto dell'applicazione, quindi non si dovrebbero usare le variabili locali.

A parte quella piccola cosa:

Sono alle prese con lo stesso problema, e tutto sembra funzionare anche per me. Raccomanderei di stare molto attento al tempo di scaricamento/uscita, tuttavia, dal momento che se si utilizza il ciclo degli eventi da un'altra applicazione e tale ciclo di eventi viene interrotto prima che la libreria venga scaricata, possono verificarsi tutti i tipi di cattiva cattiveria quando si tenta di chiudere() socket ed eliminare QObjects.

6

Studiando il codice Qt sembra che QCoreApplication sia necessario per inviare messaggi a livello di sistema come eventi timer.Cose come segnale/slot e persino QThreads non dipendono da esso a meno che non siano correlate a quei messaggi di sistema. Ecco come faccio a farlo in una libreria condivisa (in modo cross platform usando Qt stessa) e in realtà faccio chiamare exec, perché processEvents() da solo non elabora tutto.

ho un namespace globale:

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

Ho un metodo diopenapp in un QObject (cioè moc'ed) come questo:

// 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(); 
} 

E qui è Slot di OnExec:

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

Finora sembra funzionare bene, non sono sicuro di dover eliminare l'app alla fine, aggiornerò la mia risposta se trovo qualcosa.

+0

dashey - come ha funzionato per te? – ExpatEgghead

+0

@ExpatEgghead Funziona davvero bene (https://github.com/dashy/CereLink) – dashesy

+0

E finalmente ha funzionato anche per me. Tempo in più. – ExpatEgghead

3

Penso che le classi "MFC to Qt Migration" possano aiutarti.

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

+0

Scusa se pensavo che il post fosse di quest'anno ... – Gojir4

+2

Non c'è bisogno di scusarsi. Le risposte sono sempre benvenute, non importa se la domanda è vecchia. Tuttavia, sarebbe meglio evitare [link only answers] (http://meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers). Quindi potresti voler migliorare la tua risposta. Non limitarti a copiare e incollare il contenuto. :) – Bart

+0

Questa è la risposta giusta per l'esecuzione di widget Qt o DLL in un'applicazione MFC. – Matthew

Problemi correlati