Shared library - Klasse exportieren?
-
Hi!
Dynamische Bibliotheken sind für mich unter Linux und C++ noch Neuland.
Ich versuche, eine Klasse in eine dynamische Bibliothek zu packen, aber irgendwie fehlt mir jeglicher Ansatz. Da ich dazu auch eigentlich nichts im Internet gefunden habe, wollte ich jetzt hier mal fragen:Ist das möglich?
Wenn ja, wie?Vorgestellt hab ich mir das ganze so:
Ich schreibe die header- und dazugehörige cpp-Datei und inkludiere sie dann in die main.cpp der Lib. Desweiteren hab ich einfach eine exportierte Funktion, die mir ein Objekt von der Klasse erzeugt, in etwa so:#include "foo.h" extern "C" { Foo* CreateFoo() { return new Foo(); } }
hat sich aber nicht erzeugen lassen.
Dann hab ich noch verschiedene ähnliche Dinge ausprobiert, die aber alle nicht geklappt haben.Was mir jetzt noch spontan einfällt, wäre eine Klasse zu basteln und dann irgendwie ableiten, was aber wiederum zum Problem mit der Erzugung des Objektes führt
Ich hoffe, ich habs verständlich geschrieben.
MfG
capitalismslutEDIT: Falls wichtig, ich verwende CodeBlocks mit dem GCC unter Ubuntu.
-
-
Danke für den Link, hat mir schon sehr viel weiter geholfen.
Erzeugen kann ich jetzt schon die lib und das eigentliche Programm ohne Probleme. [EDIT: Mittlerweile benutze ich kein CodeBlocks mehr sondern simepel und einfach gedit und den terminal]
Allerdings bekomm ich jetzt beim Ausführen folgende Fehlermeldung:prog: symbol lookup error: ./libDataLayer.so: undefined symbol: _ZN10CDataLayerC1Ev
libDataLayer.so und prog liegen im gleichen Verzeichnis.
So rufe ich das Program auf:LD_LIBRARY_PATH=. ./prog
nm libDataLayer.so
liefert folgendes:
00000000000007fc T CreateDataLayer 0000000000201038 d DW.ref.__gxx_personality_v0 0000000000000836 T DestroyDataLayer 0000000000200e30 a _DYNAMIC 0000000000200fe8 a _GLOBAL_OFFSET_TABLE_ w _Jv_RegisterClasses U _Unwind_Resume@@GCC_3.0 U _ZN10CDataLayerC1Ev U _ZN10CDataLayerD1Ev U _ZdlPv@@GLIBCXX_3.4 U _Znwm@@GLIBCXX_3.4 0000000000200e10 d __CTOR_END__ 0000000000200e08 d __CTOR_LIST__ 0000000000200e20 d __DTOR_END__ 0000000000200e18 d __DTOR_LIST__ 0000000000000990 r __FRAME_END__ 0000000000200e28 d __JCR_END__ 0000000000200e28 d __JCR_LIST__ 0000000000201040 A __bss_start w __cxa_finalize@@GLIBC_2.2.5 0000000000000870 t __do_global_ctors_aux 0000000000000750 t __do_global_dtors_aux 0000000000201030 d __dso_handle w __gmon_start__ U __gxx_personality_v0@@CXXABI_1.3 0000000000201040 A _edata 0000000000201050 A _end 00000000000008a8 T _fini 00000000000006a0 T _init 0000000000000730 t call_gmon_start 0000000000201040 b completed.6458 0000000000201048 b dtor_idx.6460 00000000000007d0 t frame_dummy
Ich erzeuge libDataLayer.so und prog wie folgt:
g++ -fPIC -shared main_datalayer.cpp -o ./libDataLayer.so g++ main.cpp -ldl -o ./prog
Was mich nun aber am meisten wundert, ist, dass "ldd prog" mir zwar ein paar libs auflistet, aber meine libDataLayer.so nicht dabei ist.
Und zu guter Letzt hier noch der relevante Quelltext der main.cpp:
#include <dlfcn.h> #include <iostream> #include "datalayer.h" using namespace std; int main(int argc, char** argv) { void* handle = dlopen("./libDataLayer.so", RTLD_LAZY); CDataLayer* (*createDataLayer)(); void (*destroyDataLayer)(CDataLayer*); createDataLayer = (CDataLayer* (*)())dlsym(handle, "CreateDataLayer"); destroyDataLayer = (void (*)(CDataLayer*))dlsym(handle, "DestroyDataLayer"); CDataLayer* datalayer = (CDataLayer*)createDataLayer(); destroyDataLayer(datalayer); dlclose(handle); return 0; }
und mai_datalayer.cpp:
#include "datalayer.h" extern "C" CDataLayer* CreateDataLayer() { return new CDataLayer(); } extern "C" void DestroyDataLayer(CDataLayer* dl) { delete dl; }
MfG
capitalismslut
-
c++filt kann dir das C++-Namemangling in normales C++ übersetzen. Demnach ist _ZN10CDataLayerC1Ev der Name für CDataLayer::CDataLayer(). Es fehlen also Ctor und (vermutlich) Dtor von CDataLayer. Siehe auch das U in der Ausgabe von nm. Du solltest außerdem überprüfen, ob der Aufruf von dlopen nicht fehlschlägt!
Übrigens gilt es als sehr schlechter Stil C als Prefix für Klassennamen zu verwenden.
-
GNUs nm hat eine Kommandozeilenoption dafür. Versuch's mal mit
nm -C libDataLayer.so
bzw. eigentlich besser
nm -C -D libDataLayer.so
denn bei einer dynamischen Bibliothek interessiert dich eher die dynamische Symboltabelle.
-
capitalismslut schrieb:
Ich erzeuge libDataLayer.so und prog wie folgt:
g++ -fPIC -shared main_datalayer.cpp -o ./libDataLayer.so g++ main.cpp -ldl -o ./prog
Du solltest die gebaute library auch dazu linken. Mach mal:
g++ main.cpp -lDataLayer -o ./prog
Und -ldl benötigst Du nicht.
-
Nein. Er will die Lib ja dynamisch öffnen, und nicht hinzulinken,
-
pyhax schrieb:
Nein. Er will die Lib ja dynamisch öffnen, und nicht hinzulinken,
bist du dir da sicher?
Für mich klingt das ganze eher so als ob er den code einer Klasse in eine shared lib packen möchte. Und diese klasse samt lib in einem program zu verwenden, und zwar ohne den code der klasse nochmals übersetzen zu müssen.