Python als Testumgebung für C++ library

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Francesco
User
Beiträge: 824
Registriert: Mittwoch 1. Dezember 2004, 12:35
Wohnort: Upper Austria

Hallo,

ich würde gerne ein Testprogramm für eine C++ lib (.so) in Linux für in Python erstellen. Anscheinend gibt es mehrere Möglichkeiten. In "reinem" C ist das anscheinend etwas leichter als in C++ (durch das sogenannte Namen-"mangling")
ist aber bei mir nicht der Fall (ich mein, bei mir ist es eine C++ lib)

Angenommen ich habe ein lib "mylib.so"

ideal wäre wenn ich einfach sagen könnte:
import mylib

Dann bekomme ich die Meldung

Code: Alles auswählen

>>> import mylib
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: dynamic module does not define init function 
Da wäre die Frage 1:
a) was geht hier dabei ab? (weil ich den ImportError bekomme)
b) Wie bekomme ich das Namenmangling in den Griff

Jetzt könnte ich das ganze mit ctypes importieren
zb:

Code: Alles auswählen

f = ctypes.cdll.LoadLibrary("./mylib.so")
ist das der richtigere Ansatz? Wie kann ich dann die einzelnen Funktionen (bzw. Methoden) aufrufen (und damit durchprobieren)?

Am besten wäre wahrscheinlich ein konkretes kurzes C++ Beispiel meinerseits

Um allfällige Einwänden zuvorzukommen (warum so umständlich):

Ich denke, der Ansatz "Mach doch ein Testprogramm in C++" ist langweilig ;) Ausserdem kann ich in Python sicher umfangreichere Tests (wenn das einmal funktioniert) schneller bewerkstelligen, und das ist dann interessanter... zb. könnte ich mehrere Varianten mit interaktiver Benutzereingabe (oder automatisiert durchspielen) und dies als Parameter wieder an die C++ library weitergeben
BlackJack

@Francesco: Ad 1a) Erweiterungsmodule in C sind im Grunde nur "shared objects" die bestimmten Konventionen folgen. Eine davon ist, das Python nach dem laden der Bibliothek eine `init()`-Funktion aufruft, die das Modul initialisiert, also zum Beispiel die in C implementierten Funktionen und Typen dem Python-Interpretierer bekannt macht.

Ansonsten denke ich nicht, dass es etwas für Dein Problem gibt, eben wegen dem Namemangling. Ist das überhaupt standardisiert?

Das nächste Problem bei so einem Ansatz könnten die fehlenden Metainformationen über Funktionen in "shared objects" werden. Im Regelfall enthalten die nur die Namen und Adressen von Funktionen, aber keine Infos über die Anzahl und die Typen von Argumenten und Rückgabewerten.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Francesco hat geschrieben:b) Wie bekomme ich das Namenmangling in den Griff
Gar nicht. Ginge das so einfach, gäbe es schon längst ein ctypes für c++. Da musst du schon selbst Wrapper schreiben (oder generieren lassen -> SWIG).
Francesco
User
Beiträge: 824
Registriert: Mittwoch 1. Dezember 2004, 12:35
Wohnort: Upper Austria

Danke euch beiden für die Antworten. Oje, swig schon wieder, das wollte ich eigentlich vermeiden. Das ist mir der Aufwand dann doch wieder nicht wert. Darum ist auch das ganze wxwidgets mit swig gewrappt. Hätten das sicher einfacher gelöst, wenns möghlich wäre. Und bei gtk gibt es AFAIK das Problem nicht, weil alles in reinem C implementiert wurde. ;)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Francesco hat geschrieben:Und bei gtk gibt es AFAIK das Problem nicht, weil alles in reinem C implementiert wurde. ;)
Ja, bei GTK+ gehen sie sogar einen Schritt weiter und bieten über gobject-introspection auch die nötigen Metadaten wie anzahl und Typ der Parameter zusätzlich an, so das Bindings sogar zur Laufzeit automatisch generiert werden können.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
lunar

@BlackJack: Die Umsetzung von Namen auf Symbole ist in C++ genauso gut oder schlecht standardisiert wie in C. Der Sprachstandard sagt nichts darüber aus, auch in C werden Funktionsnamen nicht notwendigerweise direkt auf Symbolnamen umgesetzt. Für bestimmte Kombinationen von Plattform und Compiler allerdings gibt es feste Standards. Ansonsten gäbe es ja gar keine kompatiblen C- oder C++-Compiler. Der für Linux relevante Standard ist die Itanium C++ ABI, welche im icc und im gcc Verwendung findet. Dort ist auch das Name Mangeling spezifiziert. Für Windows gibt es äquivalente Dokumente, die ich aber nicht kenne.

Am Verhältnis zwischen dem Mangeling-Kapitel und dem Rest dieses Standards erkennt man aber auch, dass Name Mangeling nur ein Teil des Problems ist, und wahrscheinlich nicht einmal der größte. Schließlich muss man sich auch um den Rest wie Aufrufkonventionen, Ausnahmebehandlung und Binärlayout von Typen inklusive virtueller Funktionen kümmern. Gerade dieser Teil ist bei C viel einfacher, schlicht weil C das meiste gar nicht kennt. Aufrufkonventionen sind trivial, Ausnahmen gibt es nicht, und Strukturen viel einfacher als Klassen.

Ein C++-ctypes scheitert sicherlich nicht am Demangling, sondern wohl viel eher an der großen Komplexität des gesamten Laufzeitmodells von C++.
Francesco
User
Beiträge: 824
Registriert: Mittwoch 1. Dezember 2004, 12:35
Wohnort: Upper Austria

lunar hat geschrieben:Ein C++-ctypes scheitert sicherlich nicht am Demangling, sondern wohl viel eher an der großen Komplexität des gesamten Laufzeitmodells von C++.
Ich habe das jetzt so gelöst: Ich habe mehr oder weniger eine Schnittstellenbibiliothek in C gemacht, in der ich die Objekte und Methode, die ich brauche, mit extern "C" dem Python Modul unkompliziert zur Verfügung stelle. Mit ctypes muss man dann manchmal umwandeln (pointer auf byte array zb). "By default functions are assumed to return the C int type. Other return types can be specified by setting the restype attribute of the function object." (http://docs.python.org/library/ctypes.html)

Wahrscheinlich gibts bessere Möglichkeiten (mit wrappern zb), aber ich wollte aber mit möglichst kurzem Zeitaufwand eine Lösung finden. Und soviele Funktionen waren es dann auch wieder nicht.
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Hmm, könnte man dann auch Cython als Zwischenschicht verwenden? Wäre das sinnvoll?
lunar

@mkesper: Das kommt auf die cython-Version an. Ältere Versionen verstehen eigentlich nur C, C++ ist zwar möglich, aber nicht schön, und erst recht nicht komfortabel. So oder so schreibt man also eine Schnittstellen-Bibliothek in C, es ist also mehr oder weniger egal, ob mit cython oder direkt mit C und ctypes. cython hat eigentlich nur die schönere Syntax.

Die aktuelle Version 0.13 dagegen unterstützt C++ und bietet syntaktischen Zucker für Templates, Operatoren, usw. an. Man kann C++-Bibliotheken daher relativ direkt mittels cython an Python anbinden, und muss keine C-Schnittstelle um die Bibliothek herum bauen. Insofern wäre cython 0.13 wahrscheinlich wirklich sinnvoller als C und ctypes.

Aber das muss der OP entscheiden, ich persönlich halte von der gesamten Idee, verschiedene Sprachen zum Testen und zur Implementierung zu nutzen, nicht viel. Letztlich implementiert man so eigentlich überflüssigerweise Anbindungen an eine andere Sprache und testet dann vor allem eben diese Anbindung und nicht die Bibliothek selbst. Es ist ja nun auch nicht so, als gäbe es keine Unit-Testing-Bibliotheken für C++.
BlackJack

@lunar: Es macht schon einen Unterschied ob man Tests in einer statischen Sprache schreibt und testet, oder die Tests dynamisch in einer interaktiven Umgebung entwickeln kann, im Sinne von, mal probieren was passiert wenn ich das so oder mit diesen Werten Aufrufe.
lunar

@BlackJack: Natürlich, aber eine dynamische interaktive Umgebung kann, sei sie auch noch so bequem, Tests in der statischen Sprache nicht ersetzen, zumindest nicht, wenn eine zusätzliche Zwischenschicht (in diesem Fall die C-Schicht mit den ctypes-Wrappern) dazu nötig ist. Denn wie gesagt, letztlich testet man so vor allem diese Zwischenschicht und nur mittelbar die eigentliche Bibliothek selbst. Die Anbindung ist ja nicht per definitionem korrekt und fehlerfrei. Insofern halte ich direkte Tests in der Sprache, in der die Bibliothek später auch verwendet werden soll (in diesem Fall C++) schon für obligatorisch, die Python-Umgebung kann bei der Entwicklung dieser Tests zwar helfen, sie aber keinesfalls ersetzen. Ist jetzt nur meine ganz persönliche Einschätzung ...
Antworten