Probleme mit dem SWIG beispiel

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
basti2s
User
Beiträge: 29
Registriert: Samstag 14. November 2020, 08:36

Hallo,

wie ich bereits in einem anderm Thema geschrieben habe möchte ich einen C++ Code mit über 1000 Zeilen Code in meinem Python Programm benutzen.
Dazu wollte ich mir zunächst swig aneignen.
Ich bearbeite gerade das Beispiel auf der Seite von SWIG: http://www.swig.org/tutorial.html

Die Example.c und example.i Datei habe ich 1:1 kopiert und dann folgendes ausgeführt:

Code: Alles auswählen

swig -python example.i
gcc -fpic -I/usr/include/python2.7 -c example_wrap.c
gcc -shared example_wrap.o -o example.so
wenn ich dann in meinem Python Skript import example aufrufe kommt folgende Fehlermeldung:

Code: Alles auswählen

>>> import example
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: ./example.so: undefined symbol: My_variable
Was mache ich falsch?
Thants
User
Beiträge: 34
Registriert: Dienstag 1. Dezember 2020, 12:00

Ein "undefined symbol"-Fehler taucht dann auf, wenn eine dynamische Bibliothek (deine *.so) geladen wird und diese etwas (z.B. Funktion oder Variable) benutzen will, was nirgends definiert ist. In deinem Fall, ist also irgendwo "My_variable" deklariert, aber nirgends definiert. Das kommt fast immer dadurch, dass man entweder vergessen hat, eine bestimmte Bibliothek (in der das Symbol definiert ist) einzubinden oder dass man vergessen hat, eine Datei zu übersetzen.

Der Link zu dem Tutorial, den du da angibst, enthält doch bereits die Lösung. Schau doch mal genau hin, wie dort das Modul übersetzt wird.
basti2s
User
Beiträge: 29
Registriert: Samstag 14. November 2020, 08:36

ich sehe die Lösung leider nicht :D
Vermutlich liegt der fehler darin wie ich das Modul übersetze. In meiner ersten Nachricht steht ja schon, wie ich das ganze übersetzt habe.
Ich musste ja abweichen, da ich mit der Anleitung aus dem Beispiel nicht weitergekommen bin (es kamen nur Fehlermeldungen)
Benutzeravatar
__blackjack__
User
Beiträge: 13533
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@basti2s: Du siehst die Unterschiede beim Beispiel und bei Deinen Aufrufen zum übersetzen nicht? 😳

Code: Alles auswählen

- (void)countSheep {
    unsigned int sheep = 0;
    while ( ! [self isAsleep]) { ++sheep; }
}
Thants
User
Beiträge: 34
Registriert: Dienstag 1. Dezember 2020, 12:00

basti2s hat geschrieben: Dienstag 12. Januar 2021, 15:36 Vermutlich liegt der fehler darin wie ich das Modul übersetze. In meiner ersten Nachricht steht ja schon, wie ich das ganze übersetzt habe.
Deine Vermutung ist richtig. :P Eben, und die Zeilen mit denen du das Programm übersetzt stimmen ja nicht mehr mit dem Tutorial überein.
basti2s hat geschrieben: Dienstag 12. Januar 2021, 15:36 Ich musste ja abweichen, da ich mit der Anleitung aus dem Beispiel nicht weitergekommen bin (es kamen nur Fehlermeldungen)
Aha. Wenn beim Übersetzen von example.c Fehler aufgetaucht sind, ist die Lösung allerdings nicht, den Code einfach wegzulassen. Das hat dir ja den neuen Fehler eingebrockt. Die Variable "My_variable" ist doch in example.c definiert, wenn du die also weglässt, dann existiert die Variable (was in der Fehlermeldung "Symbol" genannt wird) nicht mehr und du erhältst den "undefined symbol"-Fehler.

Also: Schritt zurück, du musst example.c wieder mit übersetzen, da das ja die Programmteile sind, die du in Python zur Verfügung stellen willst. Welchen Fehler bekommst du denn dann und was verstehst du an der Fehlermeldung nicht?
basti2s
User
Beiträge: 29
Registriert: Samstag 14. November 2020, 08:36

Okay, also erstmal vielen Dank für eure Antworten.
Ich habe das ganze jetzt nochmal versucht.

Code: Alles auswählen

 swig -python example.i
 gcc -c example.c example_wrap.c \-I/usr/include/python2.7
 ld -shared example.o example_wrap.o -o _example.so
Das habe ich so eingegeben, ich habe im vergleich zu dem Beispiel lediglich das unix % weggelassen und den Pfad für meinen Pythoninterpreter angepasst.

Wenn ich dann in einer Pythondatei import example mache kommt jetzt diese Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "example.py", line 17, in <module>
    _example = swig_import_helper()
  File "example.py", line 16, in swig_import_helper
    return importlib.import_module('_example')
  File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
ImportError: ./_example.so: undefined symbol: __aeabi_idivmod
In meinem C++ Programm existiert die Variable __aeabi_idivmod nicht.
Ebenso wenig wie in der example.i Datei
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist ein compiler-setup Problem. Da fehlt die Standardbibliothek des GCC. *Sollte* eigentlich automatisch gehen: https://wiki.osdev.org/Libgcc

Tut es aus unbekannten Gruenden nicht. Deutet auf eine verhunztes Setup hin, oder SWIG generiert komische Compiler-Optionen, oder oder oder.

Ich habe dir schon gleich zu Beginn

viewtopic.php?f=25&t=50852#p380433

gesagt, dass es mitnichten einfacher sein wird, deinen C++-Code via SWIG zu benutzen. Und du bist noch nicht mal so weit, das zu tun, sondern schon das Beispiel in SWIG stellt eine Huerde dar.

Vielleicht glaubst du mir das jetzt, und ueberlegst mal, einfach auf natives Python und das Modul spidev umzusatteln?
Thants
User
Beiträge: 34
Registriert: Dienstag 1. Dezember 2020, 12:00

@basti2s: Da es wieder ein "undefined symbol"-Fehler ist, ist es also prinzipiell das gleiche Problem wie vorher. Da scheint jetzt aber tatsächlich eine Bibliothek zu fehlen, die eigentlich beim Compiler mit dabei sein sollte (libgcc.a). Ich würde vermuten, dass es das x%y ist, was das Symbol mit einbindet (wobei es mich wundert, dass das anscheinend einen Funktionsaufruf auslöst).
Kann es sein, dass du noch irgendwelche Pakete installieren müsstest (vielleicht irgendwelche dev-Pakete?). Du kannst mal auf deinem System nach einer Datei libgcc.a suchen, ob die überhaupt irgendwo vorhanden ist.

Und vielleicht auch noch vollständigkeitshalber: was sagt denn "ldd example.so" (ldd listet die Shared Libraries auf, von denen example.os abhängt). Ist da was dabei, was als "not found" gelistet wird?

Hast du denn auf dem System schon einmal andere Programme erfolgreich übersetzt?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist standardvorgehen beim GCC auf ARM. Da die ARM Architektur zb nicht zwingend mit floating point Unit kommt, werden on einem Zwischenschritt diese pseudocalls erzeugt, die dann beim linken entsprechend der zielplattform ersetzt werden.

Und Basti hat wohl schon erfolgreich kompiliert. Das Beispiel-C++-Programm für seinen ethercat. Siehe den Thread den ich verlinkt habe.
Benutzeravatar
sparrow
User
Beiträge: 4361
Registriert: Freitag 17. April 2009, 10:28

Rein vom Aufwand her: In der Zeit hätte man diese 1.000 Zeilen Code sicher nach Python übertragen können.
basti2s
User
Beiträge: 29
Registriert: Samstag 14. November 2020, 08:36

Da habt ihr bestimmt recht. Das mag aber für euch zutreffen. Ich schau da wie der letzte Depp in den Code und wüsste garnicht wo ich anfangen soll das in Python umzuschreiben.

edit: Oder um das ganze sinnvoller zu formulieren. Wie würdet ihr da anfangen?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Indem ich mir die Dokumentation sowohl der bcm2835 Bibliothek als auch der spidev Bibliothek anschaue & versuche herauszufinden, was die Aufrufe in der einen in der anderen für eine Entsprechung haben.
Antworten