Seite 1 von 1
Q_DECL_EXPORT bei structs
Verfasst: 21. Februar 2007 22:35
von AlGaN
Hallo,
ich hab hier ein Problem mit dem Exportieren von structs in eine DLL.
Mein .pro-File:
Code: Alles auswählen
TEMPLATE = lib
DEPENDPATH += . qesp
QT -= gui
CONFIG += dll qt thread debug
DEFINES += BUILD_DLL
...
HEADERS += Buffer.hpp \
[...]
Message.hpp \
Testklasse.hpp \
XBuf.hpp
SOURCES += Buffer.cpp \
[...]
Testklasse.cpp \
XBuf.cpp
Message.hpp:
Code: Alles auswählen
#ifndef MESSAGE_H
#define MESSAGE_H
#include <QtGlobal>
#ifdef BUILD_DLL
#define EXPORT_DLL Q_DECL_EXPORT
#else
#define EXPORT_DLL
#endif
[...]
struct EXPORT_DLL sm {
...
}
[...]
#endif // MESSAGE_H
Testklasse.hpp:
Code: Alles auswählen
#ifndef TESTKLASSE_H
#define TESTKLASSE_H
#include <QTime>
#include "Message.hpp"
#ifdef BUILD_DLL
#define EXPORT_DLL Q_DECL_EXPORT
#else
#define EXPORT_DLL
#endif
class EXPORT_DLL Testklasse : public QObject
{
[...]
};
#endif
und Testklasse.cpp:
Code: Alles auswählen
#include <QtDebug>
[...]
#include "Testklasse.hpp"
[...]
Testklasse::Testklasse()
{
qRegisterMetaType<sm>("sm");
}
[...]
Obwohl ich beim struct "sm" EXPORT_DLL als Makro davorstehen habe, bekomme ich beim Kompilieren als DLL (nach Definition von BUILD_DLL im .pro-File) einen Fehler wie
"qRegisterMetaType: nichtdeklarierter Bezeichner"
"sm": Ungültige Verwendung dieses Typs als Ausdruck
Deshalb meine Frage: Da ich bisher das Export-Makro immer nur in Zusammenhang mit Klassen gesehen habe
(
), ist es möglich, auch structs in eine DLL zu exportieren? Wie muss ich dann das EXPORT-Symbol angeben ? Sind ja schliesslich nur spezielle Klassen ? Was ist mit globalen Funktionen, Variablen, Namespaces ?
Da ich auch im Web kein Tutorial zu Q_DECL_EXPORT finden konnte, wäre ich um Aufklärung dankbar.
Verfasst: 22. Februar 2007 06:31
von Christian81
Was soll es für einen Sinn haben eine structdefintion zu exportieren?
Verfasst: 22. Februar 2007 10:18
von AlGaN
Hi,
wie gesagt, die struct-Definition stellt einen erweiterten Typ dar, der in einer Signal-/Slot-Verbindung in den Klassen verwendet wird, die in die DLL exportiert werden sollen,also z.B. so:
Testklasse.hpp:
Code: Alles auswählen
#ifndef TESTKLASSE_H
#define TESTKLASSE_H
#include "Message.hpp"
#ifdef BUILD_DLL
#define EXPORT_DLL Q_DECL_EXPORT
#else
# define EXPORT_DLL
#endif
class EXPORT_DLL Testklasse : QObject
{
Q_OBJECT
[...]
signals:
void msgChanged(struct sm m);
[...]
};
#endif // TESTKLASSE_H
Testklasse.cpp:
Code: Alles auswählen
[...]
#include "Testklasse.hpp"
[...]
Testklasse::Testklasse()
{
// register Message type
qRegisterMetaType<sm>("sm");
}
void fkt()
{
struct sm = getMessage();
[...]
emit msgChanged(sm);
}
[...]
In einer anderen Klasse ist dann eben ein Slot definiert:
Testklasse2.hpp:
Code: Alles auswählen
#ifndef TESTKLASSE2_H
#define TESTKLASSE2
[...]
#include "Message.hpp"
#ifdef BUILD_DLL
#define EXPORT_DLL Q_DECL_EXPORT
#else
# define EXPORT_DLL
#endif
class EXPORT_DLL Testklasse2 : public QDialog
{
Q_OBJECT
[...]
public slots:
void updateMsg(sm m);
[...]
};
#endif // TESTKLASSE2_H
Da Testklasse und Testklasse2 beide in die DLL exportiert werden und als Signal-/Slot-Typ den struct sm verwenden, muss dieser auch in die DLL exportiert werden, die Syntax von Q_DECL_EXPORT wie bei class funktioniert aber bei structs nicht...
Es muss doch auch möglich sein, globale Funktionen, Namespaces und Variablen zu exportieren ?
Verfasst: 22. Februar 2007 10:21
von Christian81
Ich glaube Du solltest dir echt überlegen was ein struct ist - was gibts da zu exportieren? Eine struct braucht nicht exportiert zu werden (und deshalb gibts beim Versuch auch einen Compilerfehler)
Verfasst: 22. Februar 2007 10:48
von AlGaN
Meines Wissens ist der Unterschied zwischen class und struct nur, dass bei struct alle Member per Definition public sind, während sie bei class private sind, einen anderen Unterschied kenne ich nicht, lasse mich aber gerne aufklären...
Gruß,
AlGaN
Verfasst: 22. Februar 2007 10:53
von Christian81
Eine Struct war früher nur eine Klasse mit public-Varaiblen. Dass man dort auch Funktionen definieren kann, ist erst seit C++ so (wenn ich richtig liege). Auf alle Fälle ist es dadurch nicht möglich, eine struct zu exportieren. Falls deine Struct also Funktionen hat, musst Du sie wohl oder übel in eine Klasse umändern.
Und das eine struct ohne Klassen nicht exportiert werden muss ist ja im Grunde ersichtlich - ist ja nichts zum exportieren da.
Verfasst: 22. Februar 2007 18:21
von RHBaum
structs kommen aus C und sind eigentlich nen Datenverbund.
in C++ wurde es uebernommen dahingehend das structs das selbe sind wie klassen nur alle member als public.
Der c++ macht aus jeder classe sowieso soawas wie ein struct, die methoden werden einfach als member vom typ Zeiger auf Function umgesetzt.
Mit public und private hat alles hinter dem C ++ compiler sowieso gar nix mehr zu tun.
Damit sind die alten c structs compatibel zu c++, oder andersrum, c++ bleibt compatibel zu C (von der syntax her)
structs kann man exportieren ueber dll grenzen, unter C sogar der uebliche weg .... C strukturen wurden dafuer gern hergenommen wenn datentypen spaeter mal erweitert werden mussten, man brauchte ned mehr ueberall die parameter aendern .....
Die decl makros brauchst du im wesentliches fuer 2 dinge:
- ein ausschalten des name merglings, damit man z.b. mit c++ symbolnamen generieren kann die auchn c compiler lesen interpretieren kann. braucht man wenn man mit c++ ne dll mit c schnittstellen schreiben will, so das die compilerunabhaengig wird.
- festlegen der ausrichtung der parameteruebergabe und zustaendigkeit der stackverwaltung (ob aufrufer oder aufrufender den stack fuer die parameter stellt) ...
wenn dein Programm und deine dll mit den (fast)selben kompilereinstellungen generiert werden, brauchst du keine so exportdefinitionen vor die deklarationen schreiben, willst du aber ne debug mit release mixen oder ne MT mit ner ST version, kann dir unter umstaenden das name mergling probleme machen .... wenn du klassen exportierst solltest du es soweiso meiden.
In der Praxis erreichst du wenn Du eh Klassen exportierst mit den Makros soweiso nur einen effekt, naemlich die globalen compilerparameter fuer die
Parameterausrichtung zu euebrschreiben und sicherstellen das deine dll und exe die gleiche syntax bei den exportierten dingen verwenden, trotz das einer an den Schaltern rumgefummelt hat ....
Unter dem MS compiler gibts dann noch die besonderheit, das man mit nem zusaetlichen makro die exportliste fuer die DLL generieren kann, was man bei anderen compilern mit der .def datei machen muss.
Testklasse::Testklasse()
{
qRegisterMetaType<sm>("sm");
}
der kommt mit deinem typ sm ned klar .
struct EXPORT_DLL sm {
...
} ;
hinter der deklaration der struct nach der schliesenden geschweiften klammer kommt nen semikoleon ... hasst sicher nur vergessen mit zu posten ^^
signals:
void msgChanged(struct sm m);
das ist c schreibweisse, damit kommen manche c++ compiler ned klar ...
c++:
signals:
void msgChanged(sm m);
ansonsten zeig mal die struct komplett, vielleicht ist da drinne was faul ...
Ciao ....