Was wäre der schnellste Weg, um eine Python-Bindung an eine C- oder C ++ - Bibliothek zu erstellen?
(Ich benutze Windows, wenn dies wichtig ist.)
Sie sollten sich Boost.Python ansehen . Hier ist die kurze Einführung von ihrer Website:
Die Boost Python Library ist ein Framework für die Schnittstelle von Python und C ++. Sie können damit schnell und nahtlos Funktionen und Objekte von C ++ - Klassen für Python verfügbar machen und umgekehrt, ohne spezielle Tools - nur Ihren C ++ - Compiler. Es wurde entwickelt, um C ++ - Schnittstellen nicht aufdringlich zu verpacken, sodass Sie den C ++ - Code überhaupt nicht ändern müssen, um ihn zu verpacken. Boost.Python ist daher ideal, um Bibliotheken von Drittanbietern Python zugänglich zu machen. Die Verwendung fortschrittlicher Metaprogrammiertechniken in der Bibliothek vereinfacht die Syntax für Benutzer, sodass der Wrapping-Code wie eine Art deklarative Interface Definition Language (IDL) aussieht.
Das ctypes- Modul ist Teil der Standardbibliothek und daher stabiler und allgemein verfügbar als swig , was mir immer Probleme bereitete .
Bei ctypes müssen Sie alle Abhängigkeiten der Kompilierungszeit von Python erfüllen, und Ihre Bindung funktioniert für alle Pythons mit ctypes, nicht nur für die, für die sie kompiliert wurden.
Angenommen, Sie haben eine einfache C ++ - Beispielklasse, mit der Sie in einer Datei namens foo.cpp sprechen möchten:
Da ctypes nur mit C-Funktionen kommunizieren können, müssen Sie diejenigen angeben, die sie als externes "C" deklarieren.
Als nächstes müssen Sie dies zu einer gemeinsam genutzten Bibliothek kompilieren
Und schließlich müssen Sie Ihren Python-Wrapper schreiben (z. B. in fooWrapper.py).
Sobald Sie das haben, können Sie es wie nennen
quelle
extern "C" { __declspec(dllexport) Foo* Foo_new(){ return new Foo(); } __declspec(dllexport) void Foo_bar(Foo* foo){ foo->bar(); } }
Foo_delete
Funktion bereitstellen und sie entweder von einem Python-Destruktor aus aufrufen oder das Objekt in eine Ressource einschließen .Der schnellste Weg, dies zu tun, ist die Verwendung von SWIG .
Beispiel aus dem SWIG- Tutorial :
Schnittstellendatei:
Erstellen eines Python-Moduls unter Unix:
Verwendungszweck:
Beachten Sie, dass Sie Python-Dev haben müssen. In einigen Systemen befinden sich Python-Header-Dateien je nach Installation in /usr/include/python2.7.
Aus dem Tutorial:
quelle
Ich habe meine Reise in der Python <-> C ++ - Bindung von dieser Seite aus mit dem Ziel begonnen, Datentypen auf hoher Ebene (mehrdimensionale STL-Vektoren mit Python-Listen) zu verknüpfen :-)
Nachdem ich die Lösungen ausprobiert habe, die sowohl auf ctypes als auch auf boost.python basieren (und kein Softwareentwickler sind), habe ich sie als komplex empfunden, wenn eine Bindung von Datentypen auf hoher Ebene erforderlich ist, während ich SWIG gefunden habe solchen Fällen als viel einfacher .
In diesem Beispiel wird daher SWIG verwendet, und es wurde unter Linux getestet (aber SWIG ist verfügbar und wird auch unter Windows häufig verwendet).
Ziel ist es, Python eine C ++ - Funktion zur Verfügung zu stellen, die eine Matrix in Form eines 2D-STL-Vektors verwendet und einen Durchschnitt jeder Zeile zurückgibt (als 1D-STL-Vektor).
Der Code in C ++ ("code.cpp") lautet wie folgt:
Der entsprechende Header ("code.h") lautet:
Wir kompilieren zuerst den C ++ - Code, um eine Objektdatei zu erstellen:
Anschließend definieren wir eine SWIG-Schnittstellendefinitionsdatei ("code.i") für unsere C ++ - Funktionen.
Mit SWIG generieren wir einen C ++ - Schnittstellenquellcode aus der SWIG-Schnittstellendefinitionsdatei.
Wir kompilieren schließlich die generierte Quelldatei der C ++ - Schnittstelle und verknüpfen alles miteinander, um eine gemeinsam genutzte Bibliothek zu generieren, die direkt von Python importiert werden kann (das "_" ist wichtig):
Wir können jetzt die Funktion in Python-Skripten verwenden:
quelle
Es gibt auch
pybind11
eine leichtgewichtige Version von Boost.Python, die mit allen modernen C ++ - Compilern kompatibel ist:https://pybind11.readthedocs.io/en/latest/
quelle
Pytorch
pytorch.org/tutorials/advanced/cpp_extension.html Funktioniert auch vollständig unterVS Community
WindowsSchauen Sie sich Pyrex oder Cython an . Sie sind Python-ähnliche Sprachen für die Schnittstelle zwischen C / C ++ und Python.
quelle
Verwenden Sie für modernes C ++ cppyy: http://cppyy.readthedocs.io/en/latest/
Es basiert auf Cling, dem C ++ - Interpreter für Clang / LLVM. Die Bindungen sind zur Laufzeit und es ist keine zusätzliche Zwischensprache erforderlich. Dank Clang unterstützt es C ++ 17.
Installieren Sie es mit pip:
Laden Sie für kleine Projekte einfach die entsprechende Bibliothek und die Header, an denen Sie interessiert sind. Nehmen Sie beispielsweise den Code aus dem Beispiel ctypes in diesem Thread, teilen Sie ihn jedoch in Header- und Codeabschnitte auf:
Kompilieren Sie es:
und benutze es:
Große Projekte werden durch das automatische Laden der vorbereiteten Reflektionsinformationen und der cmake-Fragmente zum Erstellen unterstützt, sodass Benutzer installierter Pakete einfach Folgendes ausführen können:
Dank LLVM sind erweiterte Funktionen wie die automatische Instanziierung von Vorlagen möglich. So setzen Sie das Beispiel fort:
Hinweis: Ich bin der Autor von cppyy.
quelle
swig
,ctypes
oderboost.python
. Anstatt dass Sie Code schreiben müssen, damit Python mit Ihrem C ++ - Code funktioniert ... Python macht die harte Arbeit, um C ++ herauszufinden. Vorausgesetzt, es funktioniert tatsächlich.In diesem Artikel, in dem behauptet wird, Python sei alles, was ein Wissenschaftler braucht , heißt es im Grunde: Erster Prototyp für alles in Python. Wenn Sie dann ein Teil beschleunigen müssen, verwenden Sie SWIG und übersetzen Sie dieses Teil in C.
quelle
Ich habe es nie benutzt, aber ich habe gute Dinge über ctypes gehört . Wenn Sie versuchen, es mit C ++ zu verwenden, sollten Sie die Namensverknüpfung über vermeiden
extern "C"
. Danke für den Kommentar, Florian Bösch.quelle
Ich denke, CFFI für Python kann eine Option sein.
http://cffi.readthedocs.org/en/release-0.7/
quelle
Die Frage ist, wie man eine C-Funktion von Python aus aufruft, wenn ich das richtig verstanden habe. Dann sind Ctypes die beste Wahl (BTW portabel für alle Python-Varianten).
Eine ausführliche Anleitung finden Sie in meinem Blog-Artikel .
quelle
Eines der offiziellen Python-Dokumente enthält Details zum Erweitern von Python mit C / C ++ . Auch ohne die Verwendung von SWIG ist es recht einfach und funktioniert unter Windows einwandfrei.
quelle
Cython ist definitiv der richtige Weg, es sei denn, Sie erwarten das Schreiben von Java-Wrappern. In diesem Fall ist SWIG möglicherweise vorzuziehen.
Ich empfehle die Verwendung des
runcython
Befehlszeilenprogramms, da dies die Verwendung von Cython extrem einfach macht. Wenn Sie strukturierte Daten an C ++ übergeben müssen, schauen Sie sich die Protobuf-Bibliothek von Google an. Dies ist sehr praktisch.Hier sind einige Beispiele, die ich gemacht habe und die beide Tools verwenden:
https://github.com/nicodjimenez/python2cpp
Hoffe, es kann ein nützlicher Ausgangspunkt sein.
quelle
Zuerst sollten Sie entscheiden, was Ihr besonderer Zweck ist. Die offizielle Python-Dokumentation zum Erweitern und Einbetten des Python-Interpreters wurde oben erwähnt. Ich kann einen guten Überblick über binäre Erweiterungen hinzufügen . Die Anwendungsfälle können in 3 Kategorien unterteilt werden:
Um anderen Interessierten eine breitere Perspektive zu geben und da Ihre anfängliche Frage etwas vage ist ("zu einer C- oder C ++ - Bibliothek"), denke ich, dass diese Informationen für Sie interessant sein könnten. Unter dem obigen Link können Sie die Nachteile der Verwendung von binären Erweiterungen und deren Alternativen nachlesen.
Abgesehen von den anderen vorgeschlagenen Antworten können Sie Numba ausprobieren, wenn Sie ein Beschleunigermodul wünschen . Es funktioniert "durch Generieren von optimiertem Maschinencode mithilfe der LLVM-Compiler-Infrastruktur zur Importzeit, Laufzeit oder statisch (mithilfe des mitgelieferten pycc-Tools)".
quelle
Ich liebe Cppyy, es macht es sehr einfach, Python mit C ++ - Code zu erweitern und die Leistung bei Bedarf dramatisch zu steigern.
Es ist leistungsstark und ehrlich gesagt sehr einfach zu bedienen,
Hier ist ein Beispiel dafür, wie Sie ein Numpy-Array erstellen und an eine Klassenmitgliedsfunktion in C ++ übergeben können.
cppyy_test.py
Buffer.h
Sie können auch sehr einfach ein Python-Modul erstellen (mit CMake). Auf diese Weise vermeiden Sie, dass der C ++ - Code ständig neu kompiliert wird.
quelle
pybind11 minimal lauffähiges Beispiel
pybind11 wurde bereits unter https://stackoverflow.com/a/38542539/895245 erwähnt, aber ich möchte hier ein konkretes Anwendungsbeispiel und einige weitere Diskussionen zur Implementierung geben.
Alles in allem empfehle ich pybind11 sehr, da es sehr einfach zu verwenden ist: Sie fügen nur einen Header hinzu und dann verwendet pybind11 Template Magic, um die C ++ - Klasse zu untersuchen, die Sie für Python verfügbar machen möchten, und dies transparent.
Der Nachteil dieser Vorlagenmagie ist, dass sie die Kompilierung verlangsamt und jeder Datei, die pybind11 verwendet, sofort einige Sekunden hinzufügt. Siehe zum Beispiel die Untersuchung zu diesem Problem . PyTorch stimmt zu .
Hier ist ein minimales lauffähiges Beispiel, um Ihnen ein Gefühl dafür zu geben, wie großartig pybind11 ist:
class_test.cpp
class_test_main.py
Kompilieren und ausführen:
Dieses Beispiel zeigt, wie Sie mit pybind11 die
ClassTest
C ++ - Klasse mühelos für Python verfügbar machen können ! Beim Kompilieren wird eine Datei mit dem Namen erstellt,class_test.cpython-36m-x86_64-linux-gnu.so
dieclass_test_main.py
automatisch als Definitionspunkt für die Datei verwendet wirdclass_test
nativ definierte Modul verwendet wird.Vielleicht setzt sich die Erkenntnis, wie großartig dies ist, nur dann bemerkbar, wenn Sie versuchen, dasselbe von Hand mit der nativen Python-API zu tun. Sehen Sie sich zum Beispiel dieses Beispiel an, das etwa 10x mehr Code enthält: https://github.com /cirosantilli/python-cheat/blob/4f676f62e87810582ad53b2fb426b74eae52aad5/py_from_c/pure.c In diesem Beispiel können Sie sehen, wie der C-Code die Python-Klasse Stück für Stück mit allen darin enthaltenen Informationen (Mitgliedern, Methoden usw.) schmerzhaft und explizit definieren muss Metadaten ...). Siehe auch:
pybind11 behauptet, ähnlich zu sein,
Boost.Python
wie es unter https://stackoverflow.com/a/145436/895245 erwähnt wurde, aber minimaler, weil es von der Aufblähung befreit ist, innerhalb des Boost-Projekts zu sein:pybind11 ist auch die einzige nicht native Alternative, die in der aktuellen Microsoft Python C-Bindungsdokumentation unter https://docs.microsoft.com/en-us/visualstudio/python/working-with-c-cpp-python-in- hervorgehoben wird. Visual-Studio? view = vs-2019 ( Archiv ).
Getestet unter Ubuntu 18.04, pybind11 2.0.1, Python 3.6.8, GCC 7.4.0.
quelle