Pythonembedding unter Linux

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
gebbi
User
Beiträge: 5
Registriert: Dienstag 5. April 2011, 09:23

Hallo,
ich habe ein Problem beim Kompilieren eines shared objects meines Projektes. Unter Windows habe ich es ohne Probleme geschafft eine .dll zu kompilieren und einzubinden.
Und Linux (Ubuntu) klappt zwar das Kompilieren, aber das öffnen meiner .so durch ein weiteres Programm wird durch eine solche Fehlermeldung abgebrochen:
Couldn't open shared object (dlopen failed): ./pyMM.so: undefined symbol: PyFloat_Type

Die Datei kompiliere ich derzeit so:
gcc -Wall -fPIC -I/usr/local/include -I/usr/local/include/python2.6 -c pyMM.cpp -o pyMM.o
gcc -shared pyMM.o -L/usr/local/lib -L/usr/local/lib/python2.6 -o pyMM.so

Es scheint immer noch ein Problem beim Linken zu geben. Wie müssen denn die einzubindenden Bibliotheken aussehen? Ich habe leider nicht -so- viel Ahnung von C++ und Linux, muss das ganze aber zur Zeit für ein Projekt noch fertigstellen.
Wäre über Hilfe wirklich sehr dankbar,
ich bin wirklich langsam am Verzweifeln.

Danke im Voraus,
Gebbi
BlackJack

@gebbi: Schau mal nach einem zu Deinem Python passenden `python-config` oder `python2.6-config` und ruf das Linken so auf:

Code: Alles auswählen

gcc -shared pyMM.o $(python2.6-config --ldflags) -o pyMM.so
Beim Übersetzen wäre das sicher auch praktischer. Dann mit `--cflags`.
gebbi
User
Beiträge: 5
Registriert: Dienstag 5. April 2011, 09:23

Danke, das hat schon mal sehr geholfen. Mein Modul wird geladen und ausgeführt. Jetzt habe ich allerdings noch ein weiteres Problem, wenn ich versuche Python-Scripte zu laden und auszuführen. (Innerhalb meines Modules)
Ganz simple Strukturen funktionieren, aber bei der Datei, die er eigentlich laden soll, meldet er:

ImportError: /usr/local/lib/python2.6/lib-dynload/math.so: undefined symbol: PyExc_ValueError

Du weißt nicht zufällig auch, woher das kommt?
BlackJack

Ist `pyMM.so` ein Erweiterungsmodul für Python? Oder wird das von einem Programm als Bibliothek geladen was selbst nicht gegen die Python-Bibliothek gelinkt ist?
gebbi
User
Beiträge: 5
Registriert: Dienstag 5. April 2011, 09:23

Zweiteres. Konkret ist es eine Software die Erweiterungen anbietet, und beispielhaft einen Quellcode in C bereitgestellt hat. Ich habe nun selbst eine eine Erweiterung geschrieben, die selbst die Erweiterung um Python ermöglicht. Das "Hauptprogramm" kann ich also nicht verändern.
BlackJack

@gebbi: Ist `pyMM.so` ganz sicher gegen die Python-Bibliothek gelinkt? Schau mal nach mit `ldd`. Python-Erweiterungsmodule müssen das nämlich nicht sein, die können beim Laden die Symbole ja über den Python-Interpreter auflösen. Darum ist `math.so` zum Beispiel nicht gegen die Python-Bibliothek gelinkt.

Das ist anscheinend ein übliches Problem -- nicht nur mit Python. Man findet im Netz auch genau solche Konstellationen mit Perl und PHP. Wenn Du zwei Bibliotheken A und B hast, die beide Symbole aus C brauchen und ein Programm erst dynamisch A lädt und A dann dynamisch B lädt, reicht es nicht wenn A gegen C gelinkt ist. Entweder muss auch B gegen C gelinkt sein, oder das Programm muss es sein.

Als Notlösung kannst Du mal versuchen dem Hauptprogramm die Python-Bibliothek dynamisch unter zu schieben und das so zu starten:

Code: Alles auswählen

LD_PRELOAD=/usr/local/lib/libpython2.6.so dein_programm
gebbi
User
Beiträge: 5
Registriert: Dienstag 5. April 2011, 09:23

Nein, ist laut ldd nicht gegen Python gelinkt. Was mir beim Ausprobieren von LD_PRELOAD aufgefallen ist, dass ich keine libpython2.6.so sondern eine .a (statische Bibliothek?) habe. Kann ich eine solche nicht gegenlinken? LD_PRELOAD hat das auch so nicht angenommen mir der .a.

Die Konstellation ist übrigens, ich weiß nicht ob das richtig rüberkam, dass B gegen C gelinkt werden soll, A allerdings nicht gegen C. Letzteres kann ich auch nicht.

Riesen Dank auf jeden Fall schonmal für deine tolle Hilfe, ich verzweifel echt schon Tage lang dran.
BlackJack

@gebbi: Keine passende `libpython*.so` in `/usr/local/lib`? Das ist interessant. Da bin ich jetzt ein wenig ratlos. Hätte sonst nämlich noch ein Experiment mit `dlopen()` vorgeschlagen. :-(

Von der Konstellation bin ich ein wenig überrascht. Ich bin von `Hauptprogramm`, A = `pyMM.so`, B = `math.so`, und C = `libpython2.6.so` (o.ä.) ausgegangen. In dem Fall hättest Du wohl nur die Kontrolle gegen was A gelinkt ist, aber nicht das Hauptprogramm oder B.
lunar

@BlackJack: Das Buildsystem von CPython erzeugt keine dynamische Bibliothek, sondern man "./configure" nicht explizit "--enable-shared" übergibt.

@gebbi: Wieso verwendest Du ein selbst kompiliertes Python, anstatt die Systeminstallation für diese Zwecke zu nutzen? In jedem Fall musst Du CPython mit oben erwähnter Option neu kompilieren und installieren, um eine dynamische Bibliothek zu erhalten. Ohne diese dynamische Bibliothek ist es nicht sinnvoll möglich, den Python-Interpreter in ein anderes Programm einzubetten.
gebbi
User
Beiträge: 5
Registriert: Dienstag 5. April 2011, 09:23

Entschuldigt die späte Antwort, ich hab jetzt herausgefinden, dass ich doch eine libpython.so besitze, allerdings liegt diese in einem völlig anderen Ordner als "python2.6-config --ldflags" es mir übermittelt hat.
Hab es jetzt getestet und die komplette Kette (Hauptprogramm, mein Interface, der Python-Code) läuft.
Vielen vielen Dank nochmal!
Antworten