Python-Adventskalender 2016 Es ist der 8. Tag.
Ich habe beim diesjährigen Boost-Studium über pybind11 gesprochen, aber ich habe die Einzelheiten nicht so sehr angesprochen, deshalb ist es eine Ergänzung.
C ++ - Python-Bindungen, die mit C ++ 11 oder höher verwendet werden können. Sie können in C ++ erstellte Module in Python veröffentlichen. Empfohlen für diejenigen, die C ++ für zeitaufwändige Verarbeitung und Python für verschiedene Versuche verwenden möchten. *** Es gibt Grenzen, wie gut Sie Numpy verwenden können, daher gibt es einige Teile, die Sie in C ++ schreiben müssen. Kürzlich habe ich nur das Minimum geschrieben, das ich selbst in C ++ machen muss, und der Rest ist Stil mit Scipy, Scikit-Image usw. Es gibt Optionen wie Cython, aber die C ++ - Quelle ist immer noch einfacher als das Verfolgen und Debuggen des automatisch generierten C-Codes.
Es gibt mehrere Bindungen für Python und C ++, von denen eine Boost.Python ist. Dies selbst ist als Funktion nützlich. Ich habe vorher über Boost.Python geschrieben. (Verwenden von Python aus C ++)
Einer der Gründe, warum Python im Bereich der Berechnung von Wissenschaft und Technologie häufig verwendet wird, ist die Existenz von Numpy. Es gibt jedoch eine Bibliothek, die Boost.Python mit dem Namen Boost.Numpy verwendet. Wenn Sie dies verwenden, ist Numpy eine C ++ - Funktion. Dies ist sehr praktisch, da Sie die in erstellten Daten problemlos weitergeben können. Dies ist auch zuvor geschrieben.
Boost.Python ist jedoch ärgerlich, da eine Bibliothek erstellt werden muss. Es kann missverstanden werden, dass Boost.Python sowohl in Python2- als auch in Python3-Serien verwendet werden kann. Um es jedoch in der Python2-Serie zu verwenden, müssen Sie 2 Serien erstellen, und um es in der Python3-Serie zu verwenden, müssen Sie 3 Serien erstellen. Sie müssen auch eine Debug-Version, einen statischen Link oder einen dynamischen Link auswählen. Natürlich muss auch Boost.Numpy gebaut werden.
Pybind11 ist eine Alternative zu solch nervigem Boost.Python.
Es kann nicht mit Compilern verwendet werden, die C ++ 11 nicht unterstützen. Lassen Sie uns einen solchen Compiler wegwerfen. Boost.Python ist aufgebläht, weil es mit älteren Compilern funktioniert, aber Pybind 11 ist klein, weil es nur auf C ++ 11 und höher abzielt.
Boost.Python erforderte einen Bibliotheksaufbau und war mühsam zu installieren, aber pybind11 ist nur für den Header und einsatzbereit. Ich denke, dieser Vorteil allein ist ein Grund, zu pybind11 zu wechseln.
Die Migration von Boost.Python ist relativ einfach. Wenn Sie C ++ 11 verwenden können, ziehen Sie es jetzt in Betracht.
Die Zusammenarbeit mit der C ++ - Matrixbibliothek Eigen und der Python-Array-Bibliothek Numpy wurde bereits in Betracht gezogen. Sie müssen Boost.Numpy nicht separat wie Boost.Python installieren und keine Bibliothek erstellen.
Da es sich nur um einen Header handelt, klonen oder laden Sie es einfach von github herunter und legen Sie es in Ihrem Lieblingsverzeichnis ab. Möglicherweise können Sie es mit dem OS-Paketmanager installieren, aber es scheint häufig aktualisiert zu werden. Ich denke, Sie sollten es von github herunterladen. Ich habe festgestellt, dass die von Package Manager installierte Version alt war und es keine Funktion gab, die in der neuesten Version enthalten sein sollte.
Verwenden wir die in C ++ aus Python erstellte Additionsfunktion. Gleich wie in der offiziellen Dokumentation.
cppmod.cpp
#include<pybind11/pybind11.h>
int add(int i, int j) {
return i + j;
}
PYBIND11_MODULE(cppmod, m) {
m.doc() = "pybind11 example plugin";
m.def("add", &add, "A function which adds tow numbers");
}
Da es sich um eine gemeinsam genutzte Bibliothek handelt, gibt es keine Hauptfunktion. Der von PYBIND11_PLUGIN angegebene Name ist der Modulname. Mit anderen Worten, wenn Sie Python verwenden, ist es in diesem Beispiel "import cppmod".
Das folgende `py :: module``` ist eine Beschreibung des Moduls. Der Name und der sogenannte Docstring. Geben Sie als Nächstes die Funktion an, die in Python veröffentlicht werden soll. Die letzte
return m.ptr ()
`` wurde in Boost.Python nicht benötigt, sollte aber in pybind11 hinzugefügt werden.
Als Referenz im Fall von Boost.Python
BOOST_PYTHON_MODULE(cppmod) {
Py_Initialize();
py::def("add",add);
}
Es wird sein. Es ist fast das gleiche.
Kompilieren Sie als gemeinsam genutzte Bibliothek (DLL für Windows, jedoch mit der Erweiterung .pyd). ~~ Da ich SCons verwende, sieht die Konfigurationsdatei folgendermaßen aus: Bitte je nach Umgebung einstellen. SCons ist übrigens ein Build-Tool für Python. Es wird gesagt, dass es langsam ist, wenn es ein großes Projekt ist, aber die C ++ - Kompilierung selbst ist langsam, also benutze ich es, ohne mir darüber Sorgen zu machen. .. ~~ Ich habe mich für cmake entschieden, ohne dem Trend zu widersprechen. Schreiben Sie etwas wie das Folgende in CMakeLists.txt.
CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(cppmod)
set(PYBIND11_CPP_STANDARD -std=c++14)
set(CMAKE_CXX_FLAGS "-Wall -Wextra -O2")
add_subdirectory(pybind11)
pybind11_add_module(cppmod SHARED cppmod.cpp)
Der Befehl build sieht folgendermaßen aus.
$ mkdir build && cd build
$ cmake ..
$ make
Platzieren Sie zunächst die kompilierte gemeinsam genutzte Bibliothek (z. B. `` `cppmod.cpython-36m-x86_64-linux-gnu.so```) in dem Verzeichnis, in dem Sie Python ausführen möchten.
Starten Sie dann Python und importieren Sie es. Lassen Sie uns zunächst Hilfe ausgeben. Es sollte so aussehen:
input
>>> import cppmod
>>> help(cppmod)
output
Help on module cppmod:
NAME
cppmod - pybind11 example plugin
FUNCTIONS
add(...) method of builtins.PyCapsule instance
add(int, int) -> int
A function which adds two numbers
FILE
/path/to/cppmod.so
Das Modul, die Funktionsbeschreibung (docstring), das Funktionsargument und der Rückgabetyp usw. werden angezeigt.
Als nächstes verwenden wir die Funktion add.
>>> cppmod.add(2,3)
5
Ich konnte eine in C ++ erstellte Funktion aufrufen.
Verwenden Sie den Header pybind11 / numpy.h
. Eine Klasse namens py :: array_t kann Daten vom Typ ndarray empfangen und an Python übergeben.
#include<pybind11/pybind11.h>
#include<pybind11/numpy.h>
#include<algorithm>
namespace py = pybind11;
auto npadd(py::array_t<double> arr, const double v) {
const auto size = arr.size();
py::array_t<double> ret(size);
std::transform(
arr.data(),arr.data()+size,
ret.mutable_data(), [v](autoe){returne+v;});
return ret;
}
PYBIND11_MODULE(cppmod, m) {
m.doc() = "pybind11 example plugin";
m.def("npadd", &npadd, "A function which adds scalar to ndarray");
}
Anwendungsbeispiel
>>> import cppmod
>>> import numpy as np
>>> x = np.arange(10)
>>> cppmod.npadd(x, 3.)
array([ 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.])
Es ist sehr leicht.
Ich habe Dokumentation, aber es scheint, dass es noch keine Referenz für jede Funktion gibt. Es ist in Ordnung, wenn Sie sich den Quellcode ansehen, aber vielleicht haben nur C ++ Chotdekir-Leute kein Problem.
pybind11 Es ist praktisch, also lass es uns benutzen.
Recommended Posts