DLL erzeugen mit Qt für andere MFC-Anwendungen

Alles rund um die Programmierung mit Qt
Antworten
john
Beiträge: 110
Registriert: 14. August 2004 20:55
Wohnort: München

DLL erzeugen mit Qt für andere MFC-Anwendungen

Beitrag von john »

Hallo,

muss leider etwas ausholen: Ich habe die Möglichkeit in einer bestimmten MFC-Anwendung selbst erstellte DLL's zu laden und diese zu nutzen. Diese Anwendung bietet ein Script-Interface in der man externe DLL's laden kann. Ich will über das Script-Interface bestimmte Daten einer DLL übermitteln. Die DLL soll diese dann über TCP an einem Server senden, der diese auswertet und über das Netzwerk die Ergebnisse zurücksendet (alles über TCP). Ich habe mit Qt5.4 die Netzwerkprogrammierung realisiert. Ganz easy und hauptsächlich mit QTcpSocket. Auch das Signal-Slot-Konzept wird genutzt. Diese Qt C++ Klasse funktioniert auch, habe mir dazu nur eine kleine Qt-Konsolenanwendung geschrieben um zu testen.

Mit dem QtCreater habe ich ein neues Projekt erstellt und als Shared-Lib deklariert. Er kompiliert auch und ich habe eine DLL. Jedoch kann die MFC-Anwendung (die ich erweitern will) die DLL nicht laden (weil es keinen Einstiegspunkt gibt). Der QtCreator hat einfach meine Klasse Client in eine DLL gepackt. Wie bekomme ich jetzt eine DLL mit dem Einsprungspunkt (vermutlich MainDLL)?

Hier nun einer meine zig Versuche die kleine Konsolenanwendung in eine DLL mit DllMain auszulagern:

Code: Alles auswählen

#include <QCoreApplication>
#include <qt_windows.h>
#include "client.h"

int main(int argc, char *argv[])
{
    argc =0;
    QCoreApplication MyApp(argc, NULL);
    Client cl;
    return MyApp.exec();
}

BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID lpReserved)
{
    UNREFERENCED_PARAMETER(lpReserved);

    switch (fdwReason)
    {
    case DLL_PROCESS_ATTACH:
        {
            HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)main, (LPVOID)hInstance, 0, NULL);
            if (hThread != NULL)
                break;
            else
                return FALSE;
        }
    }
    return TRUE;
}

Jedoch lässt sich das nicht kompilieren. Ich bekomme folgende Ausgaben:
21:40:50: Führe Schritte für Projekt Client aus...
21:40:50: Unveränderte Konfiguration, qmake-Schritt wird übersprungen.
21:40:50: Starte "C:\Qt\Tools\QtCreator\bin\jom.exe"
C:\Qt\Tools\QtCreator\bin\jom.exe -f Makefile.Release
cl -c -nologo -Zm200 -Zc:wchar_t /Gz -O2 -MD -GR -W3 -w34100 -w34189 -EHsc -DUNICODE -DWIN32 -DCLIENT_LIBRARY -DQT_NO_DEBUG -DQT_NETWORK_LIB -DQT_CORE_LIB -DNDEBUG -I"..\Client" -I"." -I"..\..\..\..\Qt\5.4\msvc2010_opengl\include" -I"..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtNetwork" -I"..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtCore" -I"release" -I"..\..\..\..\Qt\5.4\msvc2010_opengl\mkspecs\win32-msvc2010" -Forelease\ @C:\DOKUME~1\john\LOKALE~1\Temp\client.obj.1616.0.jom
client.cpp
..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtCore/qatomic_msvc.h(120) : error C2373: '_InterlockedCompareExchange': Neudefinition; unterschiedliche Modifizierer
C:\Programme\Microsoft Visual Studio 10.0\VC\INCLUDE\intrin.h(214): Siehe Deklaration von '_InterlockedCompareExchange'
..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtCore/qatomic_msvc.h(121) : error C2373: '_InterlockedExchange': Neudefinition; unterschiedliche Modifizierer
C:\Programme\Microsoft Visual Studio 10.0\VC\INCLUDE\intrin.h(192): Siehe Deklaration von '_InterlockedExchange'
..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtCore/qatomic_msvc.h(122) : error C2373: '_InterlockedExchangeAdd': Neudefinition; unterschiedliche Modifizierer
C:\Programme\Microsoft Visual Studio 10.0\VC\INCLUDE\intrin.h(204): Siehe Deklaration von '_InterlockedExchangeAdd'
..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtCore/qatomic_msvc.h(131) : error C2373: '_InterlockedIncrement16': Neudefinition; unterschiedliche Modifizierer
C:\Programme\Microsoft Visual Studio 10.0\VC\INCLUDE\intrin.h(1103): Siehe Deklaration von '_InterlockedIncrement16'
..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtCore/qatomic_msvc.h(132) : error C2373: '_InterlockedDecrement16': Neudefinition; unterschiedliche Modifizierer
C:\Programme\Microsoft Visual Studio 10.0\VC\INCLUDE\intrin.h(1104): Siehe Deklaration von '_InterlockedDecrement16'
..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtCore/qatomic_msvc.h(133) : error C2373: '_InterlockedCompareExchange16': Neudefinition; unterschiedliche Modifizierer
C:\Programme\Microsoft Visual Studio 10.0\VC\INCLUDE\intrin.h(1105): Siehe Deklaration von '_InterlockedCompareExchange16'
..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtCore/qatomic_msvc.h(134) : error C2373: '_InterlockedExchange16': Neudefinition; unterschiedliche Modifizierer
C:\Programme\Microsoft Visual Studio 10.0\VC\INCLUDE\intrin.h(202): Siehe Deklaration von '_InterlockedExchange16'
..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtCore/qatomic_msvc.h(135) : error C2373: '_InterlockedExchangeAdd16': Neudefinition; unterschiedliche Modifizierer
C:\Programme\Microsoft Visual Studio 10.0\VC\INCLUDE\intrin.h(212): Siehe Deklaration von '_InterlockedExchangeAdd16'
main.cpp
..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtCore/qatomic_msvc.h(120) : error C2373: '_InterlockedCompareExchange': Neudefinition; unterschiedliche Modifizierer
C:\Programme\Microsoft Visual Studio 10.0\VC\INCLUDE\intrin.h(214): Siehe Deklaration von '_InterlockedCompareExchange'
..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtCore/qatomic_msvc.h(121) : error C2373: '_InterlockedExchange': Neudefinition; unterschiedliche Modifizierer
C:\Programme\Microsoft Visual Studio 10.0\VC\INCLUDE\intrin.h(192): Siehe Deklaration von '_InterlockedExchange'
..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtCore/qatomic_msvc.h(122) : error C2373: '_InterlockedExchangeAdd': Neudefinition; unterschiedliche Modifizierer
C:\Programme\Microsoft Visual Studio 10.0\VC\INCLUDE\intrin.h(204): Siehe Deklaration von '_InterlockedExchangeAdd'
..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtCore/qatomic_msvc.h(131) : error C2373: '_InterlockedIncrement16': Neudefinition; unterschiedliche Modifizierer
C:\Programme\Microsoft Visual Studio 10.0\VC\INCLUDE\intrin.h(1103): Siehe Deklaration von '_InterlockedIncrement16'
..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtCore/qatomic_msvc.h(132) : error C2373: '_InterlockedDecrement16': Neudefinition; unterschiedliche Modifizierer
C:\Programme\Microsoft Visual Studio 10.0\VC\INCLUDE\intrin.h(1104): Siehe Deklaration von '_InterlockedDecrement16'
..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtCore/qatomic_msvc.h(133) : error C2373: '_InterlockedCompareExchange16': Neudefinition; unterschiedliche Modifizierer
C:\Programme\Microsoft Visual Studio 10.0\VC\INCLUDE\intrin.h(1105): Siehe Deklaration von '_InterlockedCompareExchange16'
..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtCore/qatomic_msvc.h(134) : error C2373: '_InterlockedExchange16': Neudefinition; unterschiedliche Modifizierer
C:\Programme\Microsoft Visual Studio 10.0\VC\INCLUDE\intrin.h(202): Siehe Deklaration von '_InterlockedExchange16'
..\..\..\..\Qt\5.4\msvc2010_opengl\include\QtCore/qatomic_msvc.h(135) : error C2373: '_InterlockedExchangeAdd16': Neudefinition; unterschiedliche Modifizierer
C:\Programme\Microsoft Visual Studio 10.0\VC\INCLUDE\intrin.h(212): Siehe Deklaration von '_InterlockedExchangeAdd16'
..\Client\main.cpp(6) : warning C4007: 'main': '__cdecl' muss angegeben werden
Code wird generiert...
jom: C:\Dokumente und Einstellungen\john\Eigene Dateien\build-Client-Desktop_Qt_5_4_1_MSVC2010_OpenGL_32bit-Release\Makefile.Release [release\client.obj] Error 2
jom: C:\Dokumente und Einstellungen\john\Eigene Dateien\build-Client-Desktop_Qt_5_4_1_MSVC2010_OpenGL_32bit-Release\Makefile [release] Error 2
21:40:52: Der Prozess "C:\Qt\Tools\QtCreator\bin\jom.exe" wurde mit dem Rückgabewert 2 beendet.
Fehler beim Erstellen/Deployment des Projekts Client (Kit: Desktop Qt 5.4.1 MSVC2010 OpenGL 32bit)
Bei der Ausführung von Schritt "Make"
21:40:52: Verstrichene Zeit: 00:02.
Hat jemand eine Ahnung was ich falsch mache, oder was ich übersehe bzw. vergesse? Der Compiler meckert originale Header-Dateien von Qt und MSVC an. Naja, habe leider keine Ahnung mit der Windows-Programmierung. Weiß auch gar nicht wo ich da anfangen soll. Schließlich will ich bei Qt bleiben, da es einfach genial ist! Eventuell erbarmt sich vielleicht jemand, der mir das mit den DLL's grob schildern kann. Bin auch bereit viel nachzulesen und mich irgendwo einzuarbeiten. Wenn ich nur wüsste, wie man mit der WinApi am besten anfängt. Für mich ist die WinApi komplett undurchsichtig. Habe dann versucht nur mal eine DLL mit MS-VC++ 2010 ohne Qt zu erzeugen. Aber sogar bei einem frischen DLL-Projekt blicke ich mit MSVC nicht wirklich durch, -erkenne einfach nicht den Zusammenhang... :oops:

Vielen Dank für jeglichen Hinweis!!
Viele Grüße, johno


PS.: oder wie bekommt man eine einfache kleine Qt-Konsolen-Anwendung in eine DLL die man dann in andere MFC-Anwendungen laden kann?

Edit: meine Qt-Klasse "Client" habe ich bereits exportiert mit: CLIENTSHARED_EXPORT
Das hat eigentlich alles der QtCreator schon gemacht auch folgende Header erstellt (die ich auch bei meiner Klasse includiert habe):

Code: Alles auswählen

#ifndef CLIENT_GLOBAL_H
#define CLIENT_GLOBAL_H

#include <QtCore/qglobal.h>

#if defined(CLIENT_LIBRARY)
#  define CLIENTSHARED_EXPORT Q_DECL_EXPORT
#else
#  define CLIENTSHARED_EXPORT Q_DECL_IMPORT
#endif

#endif // CLIENT_GLOBAL_H
Er erzeugt ja auch eine DLL mit meiner Klasse und dessen Methoden, nur ohne Hauptprogram/Einsprungspunkt. Deshalb geht es mir nur um die main.cpp... Die den Einstiegspunkt bereitstellen soll und die Qt-Core Instanz mit meiner Klasse erzeugen soll mit der Eventloop... -das bekomme ich nicht in die DLL ausgelagert.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: DLL erzeugen mit Qt für andere MFC-Anwendungen

Beitrag von Christian81 »

Eine Qt-Dll in eine MFC-Applikation zum Laufen zu bekommen ist nicht wirklich trivial da die Qt-Eventloop laufen muss. In Qt4 gab es m.E. dazu eine Qt-Klasse oder ähnliches. Wie es in Qt5 aussieht - keine Ahnung.

/edit: Hier die Qt MFC Integration Lib mit Beispielen: https://qt.gitorious.org/qt-solutions/q ... winmigrate
Ist aber schon ewig nichts mehr dran passiert - ob es noch geht - keine Ahnung.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
john
Beiträge: 110
Registriert: 14. August 2004 20:55
Wohnort: München

Re: DLL erzeugen mit Qt für andere MFC-Anwendungen

Beitrag von john »

danke, ich denke das bekomme ich schon noch hin. Die Fehler beim Compilieren, die konnte ich zwar nicht verstehen und ein make clean half auch nicht. Dann hatte ich (zum Glück) das Build-Verzeichnis gelöscht und siehe da, es lässt sich jetzt wieder die DLL bauen. :roll:

Die DLL lässt sich nun auch in der MFC-Anwendung laden! Nur habe ich nun Probleme die Client-Klasse anzusprechen. Diese hatte ich ja exportiert. Nun ja, ich habe mir damit geholfen, dass ich diese Klasse nicht mehr exportiere und eine globale Variable mit dem Zeiger auf dessen Instanz davon in der DLL erzeugte. Dazu schreibe ich mir nun in der DLL globale Funktionen, die ich exportiere. Meine main.cpp sieht nun so aus:

Code: Alles auswählen

#include <Windows.h>
#include <QCoreApplication>
#include "Client.h"

Client *client = NULL;

int main(int argc, char *argv[])
{
    argc = 0;
    QCoreApplication app(argc, NULL);
    client = new Client();
    client->logon();
    return app.exec();
}

BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID lpReserved)
{
    UNREFERENCED_PARAMETER(lpReserved);

    switch(fdwReason)
    {
    case DLL_PROCESS_ATTACH:
        {
            HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)main, (LPVOID)hInstance, 0, NULL);
            if (hThread != NULL)
                break;
            else
                return FALSE;
        }
    }
    return TRUE;
}

bool CLIENTSHARED_EXPORT logout(void)
{
    return client->logout();
}

void CLIENTSHARED_EXPORT setPort(int p)
{
    client->setPort(p);
}
So kann ich quasi die Klasse-Client über die globalen, exportierten Funktionen anwenden. Zumindest wird jetzt die DLL geladen und meldet sich auch bei der Server-App an. Ebenso konnte ich logout() und setPort() in der MFC-Anwendung nutzen. Ganz sicher bin ich mir noch nicht, denn ab- und zu stürzt die MFC-Anwendung ab. Aber das kann auch noch wo anders liegen. Zumindest einen riesen Schritt weiter! :)

Danke dir, vielleicht schaffe ich das noch und benötige die QtWinMigrate gar nicht. Wäre mir lieber, ist aber trotzdem auch ein sehr interessantes Projekt.

Viele Grüße,
johno
john
Beiträge: 110
Registriert: 14. August 2004 20:55
Wohnort: München

Re: DLL erzeugen mit Qt für andere MFC-Anwendungen

Beitrag von john »

nur so zur Info: Läuft jetzt recht stabil. Habe nun die DLL ganz einfach erzeugt (ohne der QtEventLoop), -so klappt es ganz gut! Denke, dass das eher ein Problem der MFC-Anwendung ist, als von Qt, aber wissen tue ich es nicht! Ich verzichte also auf den Signal-Slot-Mechanismus.
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: DLL erzeugen mit Qt für andere MFC-Anwendungen

Beitrag von RHBaum »

Auch hier:
Ich verzichte also auf den Signal-Slot-Mechanismus.
D.h. keine GUI
Nur Qt STandard Klassen ... QString, Qt Container usw.
Dafür die Qt einbinden ?
Lieber in den Standard Libs schauen ... die bieten da auch support.

Ciao ...
john
Beiträge: 110
Registriert: 14. August 2004 20:55
Wohnort: München

Re: DLL erzeugen mit Qt für andere MFC-Anwendungen

Beitrag von john »

ja genau! Nur QtCore mit QtNetwork. Ich nutze es hauptsächlich wegen der Netzwerkprogrammierung. Und das ganze Qt (QString, QtContainer etc.) ist sehr angenehm.
WinApi ist furchtbar für mich ;-)
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: DLL erzeugen mit Qt für andere MFC-Anwendungen

Beitrag von RHBaum »

WinApi ist furchtbar für mich ;-)
Glaub nicht nur für dich :-) WinAPI und c++ haben aber auch ned viel gemeinsam, ausser C :-)
Also: C++ != WinAPI
Qt (QString, QtContainer etc.) ist sehr angenehm.
Definitiv.
Ich hab für mein letztes Projekt was in C# machen muessen. Eigentlich gegenüber C++ war das auch "angenehm" (schneller erfolg, man braucht sich über dinge keinen Kopf machen, die in C++ eigentlich nen alltägliches Problem sind).
Ich sag auch immer: Qt Programmieren hat mehr mit Java (oder C#) zu tun als mit C++ !
Das ist eher sinnbildlich als wörtlich zu verstehen !

Für Netzwerk gibts auch mehr C++ like Bibs. Je nach Level auf dem du aufsetzen willst.
boost z.b. wenn auf socket/stream (TCP/Ip) Ebene arbeiten willst
httplib oder curl wenn auf http Ebene Arbeiten willst.
...

Für Container und Basic Strings: STL oder boost

C++ ist das mittel der Wahl, wenn man auf Performance optimieren will / muss und / oder allgemeingültige (bindings zu mehreren Sprachen) Biblos bauen will/muss. oder man nur C++ Entwickler für sein projekt bekommt (solls auch geben).
Und da ist der Komfort von Qt nicht Umsonst (Abhaengigkeitsmanagment, multithreading optimierung). Manchmal auch zu teuer ...

Wenn sowas kein Thema ist, muss man sich auch die Frage gefallen lassen: warum dann C++ ?
Und wenn C++ zu Lernzwecken, dann sollte Qt nurn Zwischenschritt sein ...

Ciao ...
john
Beiträge: 110
Registriert: 14. August 2004 20:55
Wohnort: München

Re: DLL erzeugen mit Qt für andere MFC-Anwendungen

Beitrag von john »

Hi,
nun ja, vermutlich hast du recht. Bei mir ist das nur für den privaten Gebrauch. Ich kann nur die Sprache C/C++. -und habe etwas Qt-Erfahrung. Ich will nur relativ schnell und einfach zum Ziel kommen. Wie gesagt, es muss nicht richtig professionell sein. Es soll nur funktionieren und stabil sein.

Viele Grüße johno
Antworten