Name Mangling-Problem (dlopen, g++)
-
Hallo,
Habe das Problem, daß eine Klasse aufgelöst wird, obwohl ich das nicht brauche. Genauer gesagt möchte ich:
* Funktionen exportieren, damit ich sie via dlopen, dlsym, dlclose verwenden kann.
* in diesen Funktionen Klassen verwenden, die aber nicht exportiert werden sollen.also eine Frage wäre, wie kann ich eine Klasse "verstecken"?
Hier mein Testprogramm:
Bibliothek verwendet:
//Test.h: class Test { private: public: Test(); ~Test(); };
//Test.cpp Test::Test() { printf("constr\n"); } Test::~Test() { }
//hello.cpp #include <iostream> #include "Test.h" extern "C" { void hello() { std::cout << "hello" << '\n'; Test x=Test(); } }
Hauptprogramm:
//main.cpp #include <iostream> #include <dlfcn.h> int main() { using std::cout; using std::cerr; cout << "C++ dlopen demo\n\n"; // open the library cout << "Opening hello.so...\n"; void* handle = dlopen("./hello.so", RTLD_LAZY); if (!handle) { cerr << "Cannot open library: " << dlerror() << '\n'; return 1; } // load the symbol cout << "Loading symbol hello...\n"; typedef void (*hello_t)(); // reset errors dlerror(); hello_t hello = (hello_t) dlsym(handle, "hello"); const char *dlsym_error = dlerror(); if (dlsym_error) { cerr << "Cannot load symbol 'hello': " << dlsym_error << '\n'; dlclose(handle); return 1; } // use it to do the calculation cout << "Calling hello...\n"; hello(); // close the library cout << "Closing library...\n"; dlclose(handle); }
Compileraufruf:
* g++ -shared -rdynamic hello.cpp -o hello.so
* g++ -ldl -lpthread main.cpp -o mainProgrammaufruf:
./mainAls Fehler erhalte ich:
Cannot open library: ./hello.so: undefined symbol: _ZN4TestC1EvDiese Klasse sollte eigentlich nicht öffentlich sein, ich möchte sie lediglich innerhalb der Bibliothek verwenden.
Wenn ich
Test x=Test();
auskommentiere, läuft das Programm durch
Kann mir da jemand helfen?
Gruß
Joe
-
g++ -shared -rdynamic hello.cpp -o hello.so
Ich glaube Du hast Test.cpp in der .so vergessen.
-
Hallo,
da fehlt irgendwie der Header der das gemeinsame Interface festlegt:// hello.h #ifndef HELLO_H_INCLUDED #define HELLO_H_INCLUDED #ifdef _cplusplus extern "C" { #endif void hello(); #ifdef _cplusplus } #endif #endif // hello.cpp #include "hello.h" #include "test.h" #include <iostream> #ifdef _cplusplus extern "C" { #endif void hello() { std::cout << "hello" << '\n'; Test x=Test(); } #ifdef _cplusplus } #endif //main.cpp #include <iostream> #include <dlfcn.h> #include "hello.h" int main() { ... }
Das Ganze ist aber kein Standard-C++ Problem, deshalb geht's jetzt nach Linux/Unix.
-
Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum Linux/Unix verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Hallo,
danke mal für eure Antwortenich habs mal so probiert, leider ohne Erfolg:
Wenn man Test x=Test(); auskommentiert, funktioniert es.// hello.h #ifndef HELLO_H_INCLUDED #define HELLO_H_INCLUDED //#ifdef _cplusplus extern "C" { //#endif void hello(); //#ifdef _cplusplus } //#endif #endif // hello.cpp #include "hello.h" #include "test.h" #include <iostream> //#ifdef _cplusplus //extern "C" { //#endif void hello() { std::cout << "hello" << '\n'; Test x=Test(); } //#ifdef _cplusplus //} //#endif //main.cpp #include <iostream> #include <dlfcn.h> //#include "hello.h" int main() { ... }
Diese Modifikationen sollen garantieren, dass die Funktionen über dlsym geladen werden können, ohne dass eine Klasse bekannt sein muss.
In main.cpp war ein include "hello.h", was ich genau nicht will. Leider macht der Compiler wieder dieselben Schwierigkeiten. Nach außen sollen die Bibliothek nur C-Funktionen zur Verfügung stellen, intern möchte ich aber Klassen verwenden.Hintergrund:
ich durchsuche einen Pfad nach plugins, die dieselbe Schnittstelle aufweisen. Dort weiß ich ja nicht zur Kompilierzeit, welche Bibliotheken später geladen werden.Gruß,
Joe
-
Hast Du Test.cpp denn jetzt mit in die .so gepackt?
EDIT:
Wenn ich die Test.cpp mitkompiliere funktioniert das Beispiel natürlich einwandfrei, dass die Klasse Test erstmal noch mit exportiert wird steht auf einem anderen Blatt...Nochmal EDIT:
Erstelle eine Datei retainsym mit einer Zeile, in der "hello" steht (das Symbol was exportiert werden soll). Dann:
g++ -shared -rdynamic hello.cpp test.cpp -Wl,--retain-symbols-file -Wl,retainsym -o hello.so
-
http://herbert.the-little-red-haired-girl.org/c-tips/unix/index.html
Schau dir mal diesen Link an.
Dort wird schön beschrieben, wie man unter Linux/Unix zu Libraries kommt.
Vll. waren deine Compilerparameter "falsch".
-
Danke euch,
es funktioniert jetzt.Habe in der Testklasse vergessen, den Header einzubinden und nicht mitkompiliert.
zum Tutorial: hab ich nicht ausprobiert, da dort gcc anstelle von g++ verwendet wird.
und zum "retainsym": beide Varianten funktionieren. (mir ist es egal, ob die Klasse mitkommt, solange sie keinen Fehler verursacht.
Soviel zur Vollständigkeit (damit der Nächste auch weiß, worum es geht)
Gruß,
Joe