QLibrary: resolve gibt 0x0 -> interface darf nicht erben?
Verfasst: 4. Februar 2014 17:23
Hallo zusammen, ich bin neu im Forum. Zunächst einmal Danke fürs Lesen.
Ich nutze den QT Creator der Version 5.2 (mingw48 - opengl - x86).
Mein Programm soll eine dll während der Laufzeit laden. Es lässt sich sowohl kompillieren als auch ausführen. Jedoch gibt die resolve(..) Funktion in einem bestimmten Fall einen NULL - Zeiger zurück. Hier liegt das Problem, denn diesen bestimmten Fall brauche ich.
Zunächst der prinzipielle Aufbau des Programms:
Das Hauptprogramm benutzt Klassen, die als Unterprojekte angelegt und in Dlls (bzw. bei QT .a Dateien) untergebracht sind. Alles wird zur Kompillierzeit zusammen gelinkt.
-----------------------
// eine abstakte Klasse (eigenes Unterprojekt --> dll wird beim Kompillieren eingebunden)
class A : public QGraphicsItem
{
...
}
// eine weitere abstrakte Klasse (eigenes Unterprojekt --> dll wird beim Kompillieren eingebunden)
class B
{
...
}
Bis hier hin alles OK. Das gesamte Projekt lässt sich "builden" und ausführen ohne abzustürzen.
-----------------------
Nun zur dll, die während der Laufzeit geladen werden soll:
// eine nicht abstrakte Klasse, die von B erbt (und entsprechend alle virtuellen Funktionen implementiert)
// B ist also die Interface - Klasse
class SpecialB : public B
{
...
}
// dazu wird noch eine Funktion in dieser Dll definiert, die eine Instanz der Klasse SpecialB erzeugen soll
extern "C" MY_EXPORT SpecialB* Create(...Argumente...)
{
return new SpecialB(...Argumente...);
}
MY_EXPORT ist entsprechend der QT Hilfe definiert:
#ifdef Q_OS_WIN
#define MY_EXPORT __declspec(dllexport)
#else
#define MY_EXPORT
#endif
Auch dieses Projekt wird fehlerfrei gebaut und beim Ausführen des Hauptprogramms mittels QLibrary geladen.
-----------------------
-----------------------
Zum Verhalten:
Die Funktion "Create" soll aufgelöst werden, also: FUNC_TYPE create_func = (FUNC_TYPE)library->resolve("Create");
Dieser Befehl funktioniert problemlos, wenn die abstrakte Klasse B nicht von der abstrakten Klasse A erbt. (also das ": public A" löschen)
Es funktioniert aber nicht, (d.h. create_func == 0x0 ) wenn B von A erbt.
Es funktioniert ebenfalls nicht, wenn zwar B von A erbt, aber die Vererbung bei A von QGraphicsItem herausgenommen wird. (also das ": public QGraphicsItem" löschen - falls jemand einwenden möchte, dass QGraphicsItem ja auch Slots und der Gleichen hat, und es deswegen nicht funktioniert)
Instanzen von QGraphicsView und QGraphicsScene werden übrigens im Hauptprogramm erzeugt.
In dem QT Creator Beispiel "Elastic Nodes" sieht man zudem, dass Klassen, die von QGraphicsItem abgeleitet sind, kein Q_OBJECT makro benötigen. Daher muss auch das Interface (die abstrakte Klasse B) kein Q_OBJECT sein
Die Frage ist nun, warum darf B nicht von einer anderen Klasse (A) abgeleitet sein, nicht einmal dann, wenn sich diese Klasse (A) qualitativ nicht von B unterscheidet?
Was habe ich übersehen? Liegt es daran, dass durch die Vererbung von A an B automatisch auch A zur Interface - Klasse wird und SpecialB damit Funktionen zweier verschiedener Interface-Klassen implementiert? Falls ja, was hat das mit der Funktion "Create" zu tun?
Nochmals vielen Dank fürs Lesen und für evtl. hilfreiche Vorschläge!
Ich nutze den QT Creator der Version 5.2 (mingw48 - opengl - x86).
Mein Programm soll eine dll während der Laufzeit laden. Es lässt sich sowohl kompillieren als auch ausführen. Jedoch gibt die resolve(..) Funktion in einem bestimmten Fall einen NULL - Zeiger zurück. Hier liegt das Problem, denn diesen bestimmten Fall brauche ich.
Zunächst der prinzipielle Aufbau des Programms:
Das Hauptprogramm benutzt Klassen, die als Unterprojekte angelegt und in Dlls (bzw. bei QT .a Dateien) untergebracht sind. Alles wird zur Kompillierzeit zusammen gelinkt.
-----------------------
// eine abstakte Klasse (eigenes Unterprojekt --> dll wird beim Kompillieren eingebunden)
class A : public QGraphicsItem
{
...
}
// eine weitere abstrakte Klasse (eigenes Unterprojekt --> dll wird beim Kompillieren eingebunden)
class B
{
...
}
Bis hier hin alles OK. Das gesamte Projekt lässt sich "builden" und ausführen ohne abzustürzen.
-----------------------
Nun zur dll, die während der Laufzeit geladen werden soll:
// eine nicht abstrakte Klasse, die von B erbt (und entsprechend alle virtuellen Funktionen implementiert)
// B ist also die Interface - Klasse
class SpecialB : public B
{
...
}
// dazu wird noch eine Funktion in dieser Dll definiert, die eine Instanz der Klasse SpecialB erzeugen soll
extern "C" MY_EXPORT SpecialB* Create(...Argumente...)
{
return new SpecialB(...Argumente...);
}
MY_EXPORT ist entsprechend der QT Hilfe definiert:
#ifdef Q_OS_WIN
#define MY_EXPORT __declspec(dllexport)
#else
#define MY_EXPORT
#endif
Auch dieses Projekt wird fehlerfrei gebaut und beim Ausführen des Hauptprogramms mittels QLibrary geladen.
-----------------------
-----------------------
Zum Verhalten:
Die Funktion "Create" soll aufgelöst werden, also: FUNC_TYPE create_func = (FUNC_TYPE)library->resolve("Create");
Dieser Befehl funktioniert problemlos, wenn die abstrakte Klasse B nicht von der abstrakten Klasse A erbt. (also das ": public A" löschen)
Es funktioniert aber nicht, (d.h. create_func == 0x0 ) wenn B von A erbt.
Es funktioniert ebenfalls nicht, wenn zwar B von A erbt, aber die Vererbung bei A von QGraphicsItem herausgenommen wird. (also das ": public QGraphicsItem" löschen - falls jemand einwenden möchte, dass QGraphicsItem ja auch Slots und der Gleichen hat, und es deswegen nicht funktioniert)
Instanzen von QGraphicsView und QGraphicsScene werden übrigens im Hauptprogramm erzeugt.
In dem QT Creator Beispiel "Elastic Nodes" sieht man zudem, dass Klassen, die von QGraphicsItem abgeleitet sind, kein Q_OBJECT makro benötigen. Daher muss auch das Interface (die abstrakte Klasse B) kein Q_OBJECT sein
Die Frage ist nun, warum darf B nicht von einer anderen Klasse (A) abgeleitet sein, nicht einmal dann, wenn sich diese Klasse (A) qualitativ nicht von B unterscheidet?
Was habe ich übersehen? Liegt es daran, dass durch die Vererbung von A an B automatisch auch A zur Interface - Klasse wird und SpecialB damit Funktionen zweier verschiedener Interface-Klassen implementiert? Falls ja, was hat das mit der Funktion "Create" zu tun?
Nochmals vielen Dank fürs Lesen und für evtl. hilfreiche Vorschläge!