SharedObjects und Klassen
-
Hallo,
ich arbeite derzeit an der Lösung für folgendes Problem:
Aus einem SharedObject (.so / .dll) möchte ich die Implementierung einer Klasse (die Deklaration in Form einer Header-Datei zugrundeliegend) laden.Den bisherigen Code findet ihr auf GitHub: https://github.com/cgloeckner/sharedclasses
Hier die main.cpp - sie zeit quasi die "aktuelle Bedienung" des Ganzen:
#include "core/LibraryWrapper.hpp" namespace engine { #include "Demo.hpp" } class WrappedDemo: public LibraryWrapper<engine::Demo> { public: WrappedDemo(): LibraryWrapper<engine::Demo>("Demo", "Demo") { engine::Demo* (*create)() = (engine::Demo* (*)())( this->load_function("create_Demo") ); this->data = create(); std::cout << "WrappedDemo()" << std::endl; } WrappedDemo(double initwert): LibraryWrapper<engine::Demo>("Demo", "Demo") { engine::Demo* (*create)(double) = (engine::Demo* (*)(double))( this->load_function("create_Demo_double") ); this->data = create(initwert); std::cout << "WrappedDemo(double)" << std::endl; } ~WrappedDemo() { std::cout << "~WrappedDemo()" << std::endl; } void foo() { this->data->foo(); } int bar(double value) { return this->data->bar(value); } double get_wert() { return this->data->wert; } void set_wert(double value) { this->data->wert = value; } }; int main() { WrappedDemo* demo = new WrappedDemo(24532.2); demo->foo(); std::cout << "Wert: " << demo->get_wert() << std::endl; std::cout << "als int: " << demo->bar(demo->get_wert()) << std::endl; delete demo; }Dabei verwende ich eine Template-Klasse LibraryWrapper<T>, deren Konstruktor jede Funktionen lädt, die die eigentlichen Konstruktoren bzw. Destruktoren auslösen (siehe Demo.cpp). Wird eine Instanz von LibraryWrapper<T> zerstört, wird der ursprüngliche Destruktor aufgerufen. Dazu verwendet die Klasse intern ein geschütztes Member data vom Typ T, das die (ursprünglich vom Original-Konstruktor erstellte) Instanz des ursprünglichen Objektes enthält. Ableitungen von LibraryWrapper<T> (wie WrappedDemo, siehe main.cpp) implementieren eigene Konstruktoren (mehrere Konstruktoren sind prinzipiell so möglich). Dabei gibt es mein erstes Problem: [b]Die Funktionszeiger müssen zunächst bzgl. der Funktionssignatur gecastet werden. Das sieht (a) ziemlich hässlich aus und ist (b), wenn man viele Wrapper-Klassen so erstellen will, sehr aufwändig. Hätte jemand eine Idee, wie man das umgeht?
Das nächste bezieht sich auf die Membervariablen der ursprünglichen Klasse, die sich innerhalb des Wrappers im data-Member befinden. Um auf sie zugreifen zu können, brauche ich Getter- und Setter-Methoden (siehe main.cpp). Auch das ist ziemlich nervig, wenn es sich um mehrere größere Klassen handelt. Meine anfängliche Idee, LibraryWrapper<T> von T abzuleiten, würde die Member direkt verfügbar machen. Allerdings weiß ich nicht, wie ich dann die in C-Funktionen gewrappten Konstruktoren (und um dieses in-C-Funktionen-schreiben komme ich imho nicht drumrum - wegen der Struktur der Shared Objects) korrekt aufrufe. Die (mit der C-Funktion) erstellte Instanz darf ich ja nicht direkt auf this zuweisen.
Ich hoffe ihr wisst, auf was ich hinaus will _ Ist das denn prinzipiell überhaupt möglich, was ich mir vorstelle? Ich kann mir schwerlich vorstellen, dass die "größeren" Anwendungen (die .so bzw .dll Dateien verwenden) alles im prozeduralen, klassenlosen Stil (also Oldschool C
) behandeln.Mein Ziel ist es, mit der aus der SharedObject geladenen Klassenimplementierung weitere Vererbung und somit Spezialisierung durchzuführen.
LG Glocke
-
Ich kenn das halt eher so, dass das Plugin von einem Engine-Typen ableitet (zumeist wohl eine Schnittstelle) und nicht die Engine vom Plugin-Typen...