Frage

Ich habe grübelte über das schreiben eines peak-fitting-Bibliothek für eine Weile.Ich kenne Python ziemlich gut und planen die Umsetzung alles in Python beginnen mit aber vorstellen, dass ich zu re-implementieren Sie einige Kern-Routinen in einer kompilierten Sprache schließlich.

IIRC, eine Python ' s original Kompetenz wurde als prototyping-Sprache, aber Python ist ziemlich liberal, so dass Funktionen, funktoren, Objekte übergeben werden, die die Funktionen und Methoden, wobei ich vermute, das gleiche ist nicht wahr, sagen Sie C oder Fortran.

Was sollte ich wissen, über das entwerfen von Funktionen/Klassen, die ich ins Auge fassen müssen, um eine Schnittstelle in das kompilierte Sprache?Und wie viele dieser potenziellen Probleme behandelt werden, die von Bibliotheken wie cTypes, bgen, SCHLUCK, Boost.Python, Cython oder Python-SIP?

Für diesen speziellen Anwendungsfall (ein passendes Bibliothek) ich vorstellen, so dass die Benutzer zu definieren, der mathematische Funktionen (Guassian, Lorentz etc.) als Python-Funktionen, die dann weitergegeben werden, eine Auslegung durch den kompilierten code passend Bibliothek.Die übergabe und Rückgabe von arrays ist auch wichtig.

War es hilfreich?

Lösung

Endlich eine Frage, die kann ich wirklich einen Wert Antwort auf :).

Ich habe untersucht, f2py, boost.python swig, cython und pyrex, die für meine Arbeit (PhD in optischen Messverfahren).Ich verwendet, Schluck Sie sich ausgiebig zu steigern.python-einige-und pyrex und cython eine Menge.Ich habe auch ctypes.Das ist meine Gliederung:

Haftungsausschluss:Dies ist meine persönliche Erfahrung.Ich bin nicht mit einer dieser Projekte.

swig: spielt nicht gut mit c++.Es sollte aber name mangling Probleme bei der Verknüpfung Schritt war eine große Kopfschmerzen für mich auf linux & Mac OS X.Wenn Sie C-code und möchten es Schnittstelle zu python, es ist eine gute Lösung.Ich wickelte die GTS für meine Bedürfnisse und benötigt zu schreiben, im Grunde ein C-shared-library, die ich herstellen konnte, zu.Ich würde es nicht empfehlen.

Ctypes: Ich schrieb eine libdc1394 (IEEE-Kamera-Bibliothek) - wrapper-using ctypes und es war ein sehr straigtforward Erfahrung.Sie können den code finden Sie auf https://launchpad.net/pydc1394.Es ist eine Menge Arbeit, um konvertieren-Header zu python-code, aber dann funktioniert alles zuverlässig.Dies ist eine gute Möglichkeit, wenn Sie möchten-Schnittstelle eine externe Bibliothek.Ctypes ist auch in der stdlib python, so dass jeder kann verwenden Sie Ihren code sofort.Dies ist auch ein guter Weg, um zu spielen, um mit einer neuen lib in python schnell.Ich kann es nur empfehlen, um die Schnittstelle zu externen libs.

Boost.Python:Sehr angenehm.Wenn Sie bereits C++ - code der eigenen, die Sie verwenden möchten, in python, gehen Sie für diese.Es ist sehr einfach zu übersetzen c++ - Klassen-Strukturen in python Klasse Strukturen auf diese Weise.Ich empfehle es, wenn Sie c++ - code, den Sie in python.

Pyrex/Cython: Verwenden Sie Cython, nicht Pyrex.Zeitraum.Cython ist mehr erweiterte und mehr Spaß zu verwenden.Heute, ich mache alles mit cython, die ich verwendet, um zu tun, die mit SCHLUCK-oder Ctypes.Es ist auch der beste Weg, wenn Sie python-code läuft zu langsam.Der Prozess ist absolut fantastisch:konvertieren Sie Ihre python-Module, die in cython-Module, erstellen Sie Sie und halten profiling und optimieren, wie es noch war python (kein Wechsel der Werkzeuge erforderlich).Sie können dann bewerben Sie sich, wie viel (oder wie wenig) C-code gemischt mit Ihrem python-code.Dies ist bei weitem schneller, um dann neu zu schreiben, ganze Teile der Anwendung, die in C;Sie nur umschreiben, dass die innere Schleife.

Timings:ctypes hat die höchste Aufruf-overhead (~700ns), gefolgt von boost.python (322ns), dann direkt von Schluck (290ns).Cython hat die niedrigsten call overhead (124ns) und das beste feedback, wo Sie verbringt viel Zeit auf (cProfile Unterstützung!).Die zahlen sind aus meiner Kiste ruft eine triviale Funktion, die eine Ganzzahl zurückgibt, die aus einer interaktiven shell;Modul importieren overhead ist daher nicht terminiert, nur Funktionsaufruf-overhead.Es ist daher am einfachsten und produktivsten um python-code schnell profiling und cython mit.

Zusammenfassung:Für Ihr problem ist, verwenden Sie Cython ;).Ich hoffe, dieser überblick wird nützlich sein für einige Menschen.Ich werden gerne beantworten alle übrigen Frage.


Bearbeiten:Ich vergessen zu erwähnen:für numerische Zwecke (, dass ist, die Verbindung zu NumPy) verwenden Cython;Sie haben die Unterstützung für Sie (weil Sie im Grunde entwickeln cython für diesen Zweck).Dies sollte eine weitere +1 für Ihre Entscheidung.

Andere Tipps

Ich habe nicht verwendet, SCHLUCK-oder SIP -, aber ich finde schreiben von Python-Wrapper mit boost.python sehr mächtig und relativ einfach zu bedienen.

Ich bin mir nicht klar darüber, was Ihre Anforderungen sind für die übergabe von Typen zwischen C/C++ und python, aber Sie können das leicht tun, indem Sie entweder das aussetzen einer C++ - Typ, python, oder durch die Verwendung eines generischen boost::python::object argument für C++ - API.Sie können sich auch registrieren Wandler für die automatische Konvertierung von python-Typen in C++ - Datentypen und Umgekehrt.

Wenn Sie planen, verwenden Sie boost.python, die tutorial ist ein guter Ort, um zu starten.

Ich umgesetzt haben, ist etwas ähnlich, was Sie brauchen.Ich habe eine C++ - Funktion, die nimmt eine python-Funktion und ein Bild als Argumente, und wendet die python-Funktion für jedes pixel im Bild.

Image* unary(boost::python::object op, Image& im)
{
    Image* out = new Image(im.width(), im.height(), im.channels());
    for(unsigned int i=0; i<im.size(); i++)
    {
        (*out)[i] == extract<float>(op(im[i]));
    }
    return out;
}

In diesem Fall Bild, es ist ein C++ - Objekt ausgesetzt python (ein Bild mit float-Pixel), und op ist ein in python definierten Funktion (oder wirklich jedes python-Objekt mit einer __call__ - Attribut).Sie können dann verwenden Sie diese Funktion wie folgt (vorausgesetzt, die unäre befindet sich in den als Bild enthält, die auch Bild-und load-Funktion):

import image
im = image.load('somefile.tiff')
double_im = image.unary(lambda x: 2.0*x, im)

Wie für die Verwendung von arrays mit boost, die ich persönlich noch nicht gemacht, aber ich kenne die Funktionalität zu setzen-arrays in python mit boost ist verfügbar - diese könnte hilfreich sein.

Der beste Weg, um zu planen, um einen eventuellen übergang in kompilierten code zu schreiben, der die Leistung empfindlicher Teile als Modul von einfachen Funktionen in einem funktionale Stil (staatenlos und ohne Nebenwirkungen), die akzeptieren und kehren Sie die grundlegenden Datentypen.

Dies wird eine eins-zu-eins-Zuordnung von Ihrem Python-Prototyp-code, um die eventuelle kompilierten code, und lassen Sie ctypes einfach und vermeiden Sie eine ganze Reihe von Kopfschmerzen.

Für peak-fitting, das Sie sicherlich brauchen, um arrays verwenden, die Dinge zu komplizieren, ein wenig, aber es ist immer noch sehr machbar mit ctypes.

Wenn Sie wirklich wollen zu verwenden mehr komplizierte Datenstrukturen, oder ändern Sie die übergebenen Argumente, SCHLUCK oder Python-standard-C-extension-Schnittstelle wird lassen Sie Sie tun, was Sie wollen, aber mit einer gewissen Menge an Aufwand.

Für das, was Sie tun, können Sie auch prüfen wollen, NumPy,, die könnte tun einige Arbeit, die Sie würde wollen zu push-to-C, sowie mit einige zusätzliche Hilfe in verschieben von Daten hin und her zwischen Python und C.

f2py (Teil numpy) ist eine einfachere alternative zu SCHLUCK-und boost.python für die Verpackung C/Fortran-number-crunching-code.

In meiner Erfahrung, gibt es zwei einfache Möglichkeiten, um call-in-C-code aus Python-code.Es gibt auch andere Ansätze, von denen alle sind ärgerlich und/oder ausführlich.

Die erste und einfachste Möglichkeit ist die Erstellung einer Reihe von C-code als separate " shared library und rufen Sie dann die Funktionen in dieser Bibliothek mit ctypes.Leider vorbei alles andere als basic-Datentypen ist nicht trivial.

Der zweite einfachste Weg ist, um zu schreiben ein Python-Modul in C und Anruf-Funktionen in diesem Modul.Sie übergeben können, was Sie wollen, um diese C-Funktionen, ohne zu springen durch jeden Reifen.Und es ist einfach zu rufen Sie Python Funktionen oder Methoden, die von dieser C-Funktionen, wie Sie hier beschrieben: https://docs.python.org/extending/extending.html#calling-python-functions-from-c

Ich habe nicht genug Erfahrung mit SWIG zu bieten, intelligenter Kommentar.Und während es möglich ist, Dinge zu tun, wie die übergabe von benutzerdefinierten Python-Objekte zu C-Funktionen durch ctypes oder neu zu definieren Python-Klassen in C, diese Dinge sind ärgerlich und ausführlich und empfehle ich die Einnahme von einem der beiden Ansätze oben beschrieben.

Python ist ziemlich liberal, so dass Funktionen, funktoren, Objekte übergeben werden, die die Funktionen und Methoden, wobei ich vermute, das gleiche ist nicht wahr, sagen Sie C oder Fortran.

In C, die Sie nicht passieren können, eine Funktion als argument an eine Funktion, aber Sie übergeben können, die einen Funktionszeiger, der ist genauso gut eine Funktion.

Ich weiß nicht, wie viel das helfen würde, wenn Sie versuchen, zu integrieren, C-und Python-code, aber ich wollte nur klar ein Missverständnis.

Zusätzlich zu den oben genannten Werkzeuge, die ich empfehlen kann mithilfe von Pyrex (für die Erstellung von Python extension Module) oder Psyco (als JIT-compiler für Python).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top