[gelöst] Erben von privaten Qt Klassen (PIMPL)

Alles rund um die Programmierung mit Qt
Antworten
abelmi
Beiträge: 16
Registriert: 19. Februar 2007 14:56

[gelöst] Erben von privaten Qt Klassen (PIMPL)

Beitrag von abelmi »

Hallo zusammen,
ich habe meine eigene Implementierung der Klasse QSqlTableModel sowie QSqlTableModelPrivate (Klasse MySqlTableModel und MySqlTableModelPrivate).
MySqlTableModel erbt von QSqlQueryModel; MySqlTableModelPrivate erbst von QSqlQueryModelPrivate.

Diese und weitere Klassen habe ich in eine Bibliothek zusammengefasst. Wenn ich diese Bibliothek dynamisch übersetze (als auch Qt dynamisch), erhalte ich folgenden Linkerfehler:

Code: Alles auswählen

2>MySqlTableModel.obj : error LNK2019: unresolved external symbol "public: virtual __thiscall QSqlQueryModelPrivate::~QSqlQueryModelPrivate(void)" (??1QSqlQueryModelPrivate@@UAE@XZ) referenced in function __unwindfunclet$??0MySqlTableModelPrivate@@QAE@XZ$0
2>MySqlTableModel.obj : error LNK2019: unresolved external symbol "public: void __thiscall QSqlQueryModelPrivate::initColOffsets(int)" (?initColOffsets@QSqlQueryModelPrivate@@QAEXH@Z) referenced in function "public: virtual void __thiscall MySqlTableModel::setTable(class QString const &)" (?setTable@MySqlTableModel@@UAEXABVQString@@@Z)
Wenn ich mein Projekt statisch übersetze (als auch Qt statisch), funktioniert alles problemlos.

Hier ein Ausschnitt aus meinem Code:

Global.h mit Definition und Makros

Code: Alles auswählen

...
#ifdef BUILD_DLL 
   #define EXPORT __declspec(dllexport) 
#else 
   #define EXPORT __declspec(dllimport) 
#endif
...

MySqlTableModel.h

Code: Alles auswählen

...
class EXPORT MySqlTableModel: public QSqlQueryModel
{
// enable qt signals/slots
private:
    Q_OBJECT
    Q_DECLARE_PRIVATE(MySqlTableModel)
public:
...

MySqlTableModel_p.h

Code: Alles auswählen

...
class MySqlTableModelPrivate: public QSqlQueryModelPrivate
{
    Q_DECLARE_PUBLIC(MySqlTableModel)

public:
Habt ihr eine Idee, wie ich dieses Problem lösen kann?
Zuletzt geändert von abelmi am 18. Dezember 2009 14:17, insgesamt 1-mal geändert.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Linkst Du auch gegen QtSql ?
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
abelmi
Beiträge: 16
Registriert: 19. Februar 2007 14:56

Beitrag von abelmi »

Wenn ich meine Bibliothek als Debug Version dynamisch übersetzte, dann linke ich unter anderem auch gegen Sqld4.lib.

Wenn Wenn ich meine Bibliothek statisch übersetzte, dann wird gegen QtSqld.lib gelinkt.

Für die Release Version respektive jeweils ohne das "d" im Namen.

Die statische Version funktioniert problemlos, während die dynamische Version die oben genannten Linkerfehler verursacht. Ich denke, es hat was irgendetwas mit dem __declspec(dllexport) zu tun.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

QSqlQueryModelPrivate ist in QSql4(d).lib definiert.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Christian81 hat geschrieben:QSqlQueryModelPrivate ist in QSql4(d).lib definiert.
Werden die Symbole auch exportiert?

Im allgemeinen sollte man aber auf die Verwendung von den ganzen private-Klassen verzichten. Du hast keinen Zugriff auf den Header und musst den eh schon rüberkopieren. Dann geh doch gleich her und kopier dir die Sourcen auch mit und modifizier diese direkt.
QSqlTableModel wird intern weiterhin die QSqlTableModePrivate nutzen und nicht deine - außer du holst dir auch noch den QSqlTableModel-Header in dein Projekt und modifizierst den, damit du den pimpl-Pointer selber setzen kannst.

Kannst du mal erklären, warum du unbedingt den private-Kram auch noch modifizieren musst? Warum kannst du nicht einfach nur von QSqlTableModel ableiten?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

@franzf: Du hast Recht - QSqlQueryModelPrivate wird nicht exportiert. Warum sollte es auch... :)

Statisch geht es angeblich nur da beim statischen bauen kein Linker angeworfen wird. Wenn später die statische Lib gegen ein Executable gelinkt wird kommt der gleiche Fehler.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
abelmi
Beiträge: 16
Registriert: 19. Februar 2007 14:56

Beitrag von abelmi »

@franzf: Meine eigene Implementierung der QSqlTableModel (Klasse: MySqlTableModel) ist eine veränderte Kopie der orginal Qt Klasse, um das ursprüngliche Verhalten anzupassen.
Auch die QSqlTableModelPrivate Klasse habe ich kopiert und angepasst. Diese verwendet aber auch Methoden der Basisklasse QSqlQueryModel.

Ich müsste jetzt wohl auch die QSqlQueryModelPrivate Klasse sowie deren Basisklassen, bis hoch zur QObjectPrivate Klasse kopieren, was meiner Meinung unsinnig wäre.
abelmi
Beiträge: 16
Registriert: 19. Februar 2007 14:56

Beitrag von abelmi »

@Christian81: ja genau. Bei der QSqlQueryModelPrivate fehlt der DLL Export.

Die statische Lib konnte ich problemlos gegen das Executable linken. Das hat schon in allen meiner Projekten problemlos funktioniert. Ich vermute stark, dass in statsichen Bibliotheken alle Symbole öffentlich sind.

Edit:
Ich verwende ein statisch übersetztes Qt. Daher kommt es beim Linken meiner statischen Lib auch nicht zu einem Linkerfehler. Wenn Qt dynamisch übersetzt wäre, denke ich würde es auch zu einem Fehler kommen wie du geschrieben hast.
abelmi
Beiträge: 16
Registriert: 19. Februar 2007 14:56

Beitrag von abelmi »

Ich habe nun selbst eine Lösung für mein Problem gefunden.
Ich habe die Klasse QSqlQueryModelPrivate nun veröffentlicht, indem ich in die Deklaration der Klasse das Makro Q_SQL_EXPORT hinzugefügt und Qt neu übersetzt habe.

Code: Alles auswählen

...
class Q_SQL_EXPORT QSqlQueryModelPrivate: public QAbstractItemModelPrivate
{
...
Nun scheint alles problemlos zu funktionieren.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Qt verändern ist nicht wirklich sinnvoll - dann geht es nur mit dieser speziellen Version.
Deshalb zurück zur ersten Frage - warum brauchst du überhaupt Zugriff auf Daten von QSqlQueryModelPrivate??
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Antworten