QT-Klasse in Dll auslagern... und wieder benutzen

Alles rund um die Programmierung mit Qt
Antworten
gerome69
Beiträge: 188
Registriert: 28. April 2006 22:50
Wohnort: Berlin
Kontaktdaten:

QT-Klasse in Dll auslagern... und wieder benutzen

Beitrag von gerome69 »

Hallo zusammen,
mir fehlt der Link zu einem Tutorial für sowas. Tip dazu?!

Ich möchte halt gerne ein paar Standardklassen in eine DLL auslagern.

Was ich bisher versucht habe:

1. Mein DLL-Projekt:
qttestdll.pro:

Code: Alles auswählen

TEMPLATE = lib
QT -= gui
CONFIG += dll qt thread
TARGET += 
DEPENDPATH += .
INCLUDEPATH += .

DEFINES += BUILD_DLL
SOURCES += qttestdll.cpp
qttestdll.cpp

Code: Alles auswählen

#ifdef BUILD_DLL
  #define EXPORT_DLL Q_DECL_EXPORT
#else
  #define EXPORT_DLL
#endif

#include <QObject>

class EXPORT_DLL QtTest : public QObject {
	Q_OBJECT 
	public:
	    QtTest() {printf("Class loaded!\n");}
	    inline ~QtTest(){};
	    void printOut() {printf("Print out function!\n");}
};
Das läßt sich auch wunderbar kompilieren und ich bekomme ein qttest.dll und eine qttestdll.a

Nur wir nutze ich das Ganze?

Ich habe folgendes versucht:

Code: Alles auswählen

[...]
QLibrary myLib("QtTestDll");
	if (myLib.load()) printf("Loaded!\n"); else printf("Not loaded!\n");

	typedef void (*MyPrototype)();
	//MyPrototype myFunction = (MyPrototype) myLib.resolve("QtTest");
	MyPrototype myFunction = (MyPrototype) myLib.resolve("QtTest::printOut");
	if (myFunction) myFunction(); else printf("No Function\n");
	printf("END!\n");
Wie nicht anders zu erwarten, bekomme ich immer "No Function".

Wie instanziere ich die Klasse aus der dll korrekt? Und wie greife ich auf deren Funktionen zu?

Danke für Tips, Bernd


QtTest::QtTest() {
printf("TEST\n");
}

void QtTest::printOut() {
printf("Test out!!!\n");
}

[/code]
dontinelli
Beiträge: 146
Registriert: 22. September 2006 20:53

Beitrag von dontinelli »

Obwohl der Thread schon uralt ist: Ich wäre auch an einer Lösung interessiert...
Cheers
Don Tinelli
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Ich würde sagen - das Vorgehen ist das gleiche wie wenn man eine ganz normale andere Lib einbindet.
LIBS += mylib
INCLUDEPATH += /pfad/zu/headern
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
lepsai
Beiträge: 573
Registriert: 14. September 2004 21:33
Wohnort: Berlin
Kontaktdaten:

Beitrag von lepsai »

Dass, was du da versuchst kann nicht gehen. Funktionen innerhalb klassen gehören zur Klasseninstanz und können nicht unabhängig von einer solchen geladen werden. Der Weg ist:

Code: Alles auswählen

class QtTestFactory{
public:
 virtual QtTest* createQtTestClass() const{return new QtTest();}

};

extern "C" declspec(dllexport) QtTestFactory* _cdecl GetClassFactory(){
     return new QtTestFactory();
}

QLibrary myLib("QtTestDll"); 
 if (myLib.load()) printf("Loaded!\n"); else printf("Not loaded!\n"); 

typedef QtTestFactory*(*MyPrototype)(); 
   MyPrototype myFunction = (MyPrototype) myLib.resolve("GetClassFactory"); 

QtTestFactory* factory = myFunction();
QtTest* classInstance = factory->create();

übrigens, so funktioniert auch Q_PLUGIN_EXPORT() macro
dontinelli
Beiträge: 146
Registriert: 22. September 2006 20:53

Beitrag von dontinelli »

Und wie verwendet man die ganze Klasse und nicht nur eine einzelne Funktion?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

dontinelli hat geschrieben:Und wie verwendet man die ganze Klasse und nicht nur eine einzelne Funktion?
Hast Du dich schonmal mit C/C++ Grundlagen beschäftigt? Wie verwendest Du z.B. QWidget ? Das ist auch nichts anderes...
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
gerome69
Beiträge: 188
Registriert: 28. April 2006 22:50
Wohnort: Berlin
Kontaktdaten:

Beitrag von gerome69 »

Christian81 hat geschrieben:
dontinelli hat geschrieben:Und wie verwendet man die ganze Klasse und nicht nur eine einzelne Funktion?
Hast Du dich schonmal mit C/C++ Grundlagen beschäftigt? Wie verwendest Du z.B. QWidget ? Das ist auch nichts anderes...
Ich finde die Frage überhaupt nicht unsinnig. Meine Ursprungsfrage war doch: wie instanziere ich eine Qt-Klasse als ganzes, die in einer dll ist.

Habe es inzwischen gelöst:

Code: Alles auswählen

qtestdll.h:

#ifndef QTTESTDLL_H
#define QTTESTDLL_H

#ifdef BUILD_DLL
  #define EXPORT_DLL Q_DECL_EXPORT
#else
  #define EXPORT_DLL
#endif

#include <QObject>

class EXPORT_DLL QtTest : public QObject {
	Q_OBJECT
	public:
	    QtTest();
	    inline ~QtTest(){};
	    void printOut();
};
#endif
qtestdll.cpp:

Code: Alles auswählen

#include "qttestdll.h"

QtTest::QtTest() {
    printf("TEST\n");
}

void QtTest::printOut() {
    printf("Test out!!!\n");
}
Daraus mit folgendem Projekt-File ein dll gebaut:

Code: Alles auswählen

TEMPLATE = lib
QT -= gui
CONFIG += dll qt thread
TARGET +=
DEPENDPATH += .
INCLUDEPATH += .

DEFINES += BUILD_DLL
HEADERS += qttestdll.h
SOURCES += qttestdll.cpp
Bekomme dann: QtTestDll.dll und libQtTestDll.a (Import-Library)

Dann ein neues Projekt zum Testen:
main.cpp:

Code: Alles auswählen

#include "qttestdll.h"

int main() {
    QtTest *qtTest=new QtTest();
    qtTest->printOut();
    return 1;
}
Und im .pro-File:

Code: Alles auswählen

TEMPLATE = app
QT -= gui
CONFIG +=console
TARGET +=
DEPENDPATH += .
INCLUDEPATH += .
LIBS+=".\libQtTestDll.a"

SOURCES += main.cpp
Und voilà ich bekomme eine .exe, die die Klasse aus der dll instanziert! Das ganze ist nicht statisch gelinkt gegen die ".a". Sobald ich die dll umbenenne, sagt er, daß er wegen der fehlenden dll die Application nicht starten kann.


Gruß, Bernd
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Nunja, das war doch gar nicht so schwer. Das Export-Macro könnte man noch etwas verbessern aber sonst ist es ok so.
Ach ja - den dtor zu inlinen ist auch keine gute Idee, schon gar nicht wenn man die Klasse dazu noch exportiert.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
gerome69
Beiträge: 188
Registriert: 28. April 2006 22:50
Wohnort: Berlin
Kontaktdaten:

Beitrag von gerome69 »

Christian81 hat geschrieben: Ach ja - den dtor zu inlinen ist auch keine gute Idee, schon gar nicht wenn man die Klasse dazu noch exportiert.
Ja klar, das war ja nur ne extrem kurze gefasste Version fürs Beispiel und zum Testen, kein praktisch relevanter Code.

Gruß, Bernd
dontinelli
Beiträge: 146
Registriert: 22. September 2006 20:53

Beitrag von dontinelli »

Vielleicht steht bei mir ein elefant auf dem Schlauch, aber es klappt nicht. Ich bekomme immer eine *.so Library. Wenn ich versuche, diese einzubinden, kommt die Meldung "qtlog.h": Datei oder Verzeichnis nicht gefunden.
Dabei habe ich im Hauptprojekt die Library mit

Code: Alles auswählen

LIBS+= lib/liblog.so
eingebunden (in der *.pro natürlich).
Was mache ich falsch?

Cheers
Don Tinelli

PS: Ich habe Qt 4.2 auf openSUSE 10.2
Hier mein Code:

Code: Alles auswählen

TEMPLATE = lib
TARGET = 
DEPENDPATH += .
INCLUDEPATH += .
CONFIG += dll qt thread
DEFINES += BUILD_DLL

# Input
HEADERS += qtlog.h
SOURCES += qtlog.cpp

Code: Alles auswählen

#ifndef QTLOG_H
#define QTLOG_H

#ifdef BUILD_DLL
  #define EXPORT_DLL Q_DECL_EXPORT
#else
  #define EXPORT_DLL
#endif 

#include <QString>
#include <QTextEdit>
#include <QFile>

class QtLog : public QObject
{
	Q_OBJECT
public:
	QtLog(QTextEdit *txtLog, QString fileName, int mode);
	void addEntry(QString entry);
	bool saveToFile(QString fName);
	bool saveToFile();

private:
	QTextEdit *logText;
	QString fileName;
	int logMode;
	QFile *logFile;
	QString text;
};
#endif
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Was hat die Library mit dem Header zu tun? Der Compiler muss schon wissen wo er nach dem Header suchen soll...
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
lepsai
Beiträge: 573
Registriert: 14. September 2004 21:33
Wohnort: Berlin
Kontaktdaten:

Beitrag von lepsai »

ah, jetzt verstehe ich, du wolltest auf eine Klasse aus einer festgelinkten Dll zugreifen.... hm... na ja, dann siehe oben...
Antworten