Ich denke, es besteht die Notwendigkeit, Python mit c ++ zu erweitern und Numpys ndarray in einen c ++ - Vektor zu konvertieren. Boost :: python und boost :: python :: numpy sind in solchen Fällen nützlich. (Es scheint, dass pybind11 heutzutage auch beliebt ist. Ich wollte es früh wissen ...)
Außerdem kann Boost Python tatsächlich als ausführbare Datei erstellt werden, sodass Sie es beispielsweise mit VSCode debuggen können.
Ich werde ab 1 aus den notwendigen Paketen erklären.
Bemerkungen | ||
---|---|---|
OS | ubuntu 20.04 | Starten Sie auf Docker |
python | 3.8.2 | |
boost | 1.73.0 | |
cmake | 3.16.3 |
Installieren Sie zunächst die erforderlichen Pakete.
Die für diesen Artikel erforderlichen Pakete waren "wget", "build-essential", "cmake", "python3-dev" und "python3-pip". Bitte installieren Sie entsprechend Ihrer Umgebung.
$ apt install wget build-essential cmake python3-dev python3-pip
Überprüfen Sie außerdem den Installationsort und die Version von Python mit dem folgenden Befehl.
$ which python3
/usr/bin/python3
$ python3 --version
Python 3.8.2
Wenn Sie boost :: python :: numpy verwenden möchten, müssen Sie numpy installieren. (Es fiel mir schwer, das zu vergessen.)
$ pip3 install numpy
Laden Sie dann boost herunter und installieren Sie es. Installieren Sie die Installation gemäß Kapitel 5 des folgenden offiziellen Dokuments.
So starten Sie den Boost in einer Unix-Umgebung Boost-Download-Seite
Laden Sie boost herunter, entpacken Sie es und gehen Sie in den entpackten Ordner.
$ wget (URL für Boost herunterladen)
$ tar --bzip2 -xf boost_1_73_0.tar.bz2
$ cd boost_1_73_0
Bereiten Sie die Installation mit . / Bootstrap.sh
im entpackten Ordner vor und erstellen und installieren Sie mit. / B22
.
$ ./bootstrap.sh --with-libraries=python --with-python=python3 --with-python-version=3.8
$ ./b2 install -j8
Durch Angabe von "--with-library = python" wird nur "boost :: python" erstellt und installiert, wodurch Sie Zeit sparen. Geben Sie außerdem die Version von Python an, die zuvor mit "--with-python-version" bestätigt wurde.
(Im Fall einer anderen Umgebung wie Anaconda oder Pyenv scheinen zusätzliche Einstellungen erforderlich zu sein. Da dieser Artikel in einem Container erstellt wird, gehe ich davon aus, dass ich die Umgebung so stark verschmutzen kann, wie ich möchte.)
Standardmäßig ist Boost unter "/ usr /" installiert.
Sie können das Boost-Include-Verzeichnis und den Bibliothekspfad mit dem Befehl find
finden.
$ find /usr/ -name "*boost*" | grep include
/usr/include/c++/9/bits/boost_concept_check.h
/usr/local/include/boost
/usr/local/include/boost/chrono/typeof/boost
...
$ find /usr/ -name "*boost*" | grep lib
...
/usr/local/lib/cmake/boost_numpy-1.73.0/libboost_numpy-variant-static-py3.8.cmake
/usr/local/lib/cmake/boost_numpy-1.73.0/boost_numpy-config-version.cmake
/usr/local/lib/cmake/boost_numpy-1.73.0/libboost_numpy-variant-shared-py3.8.cmake
/usr/local/lib/libboost_numpy38.a
/usr/local/lib/libboost_python38.so.1.73
/usr/local/lib/libboost_numpy38.so.1.73
...
Erstellen wir ein Beispielmodul, das tatsächlich eine Funktion hat, die die Größe der ersten Dimension von ndarray zurückgibt.
sample.cpp
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
//Um Platzhalterkonflikte zu vermeiden(Untersuchung erforderlich)
#include <boost/python/numpy.hpp>
namespace py = boost::python;
namespace np = boost::python::numpy;
auto size(np::ndarray &a)
{
auto N = a.shape(0);
return N;
}
BOOST_PYTHON_MODULE(sample)
{
Py_Initialize();
np::initialize();
py::def("size", size);
}
Führen Sie den folgenden Befehl aus, um es mit g ++
zu kompilieren:
g++ --shared -fPIC \
-I$BOOST_INCLUDE_DIR -I/usr/include/python3.8/ \
sample.cpp -Xlinker -rpath -Xlinker $BOOST_LIB_DIR \
-lboost_python38 -lboost_numpy38 -o sample.so
$ BOOST_INCLUDE_DIR
ist der Boost-Include-Pfad und $ BOOST_LIB_DIR
ist der Boost-Bibliothekspfad, der je nach Umgebung unterschiedlich ist. In meiner Umgebung war es "/ usr / local / include / boost /" bzw. "/ usr / local / lib /", wie ich zuvor mit dem Befehl "find" bestätigt habe.
Ich verwende CMake, weil ich den Befehl je nach Umgebung ändern muss und es schwierig ist, diesen Befehl jedes Mal einzugeben.
CMakeLists.txt
cmake_minimum_required(VERSION 3.12)
project(boost-python-test)
find_package(Python3 COMPONENTS Development)
find_package(Boost COMPONENTS python38 numpy38 REQUIRED)
#Zum Debuggen: Aufgelösten Pfad anzeigen
message("## Boost_LIBRARIES: ${Boost_LIBRARIES}")
message("## Boost_INCLUDE_DIRS: ${Boost_INCLUDE_DIRS}")
message("## Python3_INCLUDE_DIRS: ${Python3_INCLUDE_DIRS}")
message("## Python3_LIBRARIES :${Python3_LIBRARIES}")
add_library(sample SHARED sample.cpp)
target_include_directories(sample PRIVATE ${Python3_INCLUDE_DIRS})
target_link_libraries(sample PRIVATE ${Boost_LIBRARIES} ${Python3_LIBRARIES})
# target_link_libraries(sample PRIVATE ${Boost_LIBRARIES})Es funktioniert einfach von alleine. Der Grund ist unbekannt.
set_target_properties(sample PROPERTIES PREFIX "") #Präfix'lib'Auslassen
(Für die Verwendung von g ++ und die Verwendung von cmake
Usw. sind detailliert. Wenn Sie sich das ansehen, können Sie alles sehen, vom Kompilierungsmechanismus bis zum oben verwendeten Mechanismus "find_package". Vielen Dank! )
Platzieren Sie dann diese sample.cpp
und CMakeLists.txt
in der folgenden Verzeichnisstruktur.
.
|-- CMakeLists.txt
|-- build
`-- sample.cpp
Build in Build.
$ cd build
$ cmake ..
$ cmake --build .
Im Build befindet sich eine Datei (gemeinsam genutzte Bibliothek) mit dem Namen "sample.so". Und wenn Sie das folgende Python-Skript in Build schreiben und ausführen, wird diese gemeinsam genutzte Bibliothek "importiert" und Sie können sehen, dass sie einwandfrei funktioniert.
test.py
import sample
import numpy as np
a = np.array([1,2,3,4], dtype=np.float32)
print(a)
size=sample.size(a)
print(size)
$ python3 test.py
[1. 2. 3. 4.]
4
Solange es als Python-Modul bezeichnet wird, ist es schwierig zu debuggen und zu verwenden. Wenn Sie es als ausführbare Datei erstellen können, können Sie die CMake-Tools usw. von VS Code verwenden, um das Debuggen zu beschleunigen.
Erstellen einer C ++ - Entwicklungsumgebung mit Remotecontainern von Visual Studio-Code Bereiten Sie die VS Code-Remote-Debugging-Umgebung unter Bezugnahme auf vor. (Es gibt auch ein Repository, mit dem ich das Repository der Umgebung im obigen Artikel verbessert habe.)
Erstellen Sie zunächst die folgende Verzeichnisstruktur in dieser Umgebung.
.
|-- CMakeLists.txt
|-- build
`-- main.cpp
CMakeLists.txt
cmake_minimum_required(VERSION 3.12)
project(boost-python-test)
find_package(Python3 COMPONENTS Development)
find_package(Boost COMPONENTS python38 numpy38 REQUIRED)
add_executable(main_app main.cpp)
target_include_directories(main_app PRIVATE ${Python3_INCLUDE_DIRS})
target_link_libraries(main_app PRIVATE ${Boost_LIBRARIES} ${Python3_LIBRARIES})
Wenn Sie zu Beginn der Hauptfunktion "Py_Initialize ()" und "np :: initialize ()" aufrufen, wie unten in "main.cpp" gezeigt, können Sie sie als ausführbare Datei erstellen.
main.cpp
#include <iostream>
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
//Um Platzhalterkonflikte zu vermeiden(Untersuchung erforderlich)
#include <boost/python/numpy.hpp>
namespace py = boost::python;
namespace np = boost::python::numpy;
int main()
{
Py_Initialize();
np::initialize();
double v[] = {1.3 , 2.4 , -5.3};
int v_size = 3;
py::tuple shape = py::make_tuple(v_size);
py::tuple stride = py::make_tuple(sizeof(double));
np::dtype dt = np::dtype::get_builtin<double>();
np::ndarray output = np::from_data(&v[0], dt, shape, stride, py::object());
np::ndarray output_array = output.copy();
std::cout << "c++ array address::" << std::endl
<< std::hex << &v[0] << std::endl;
auto *p = reinterpret_cast<double*>(output.get_data());
std::cout << "ndarray address ::" << std::endl
<< std::hex << p << std::endl;
return 0;
}
In diesem Zustand können Sie die CMake-Tools-Debug-Funktion von VSCode verwenden, um Haltepunkte festzulegen und Variablen anzuzeigen. Wenn Sie die DEBUG CONSOLE von VS Code wie in der Abbildung unten gezeigt verwenden, können Sie mit C ++ so umgehen, als wäre es eine Interpretersprache, und das Debuggen wird schneller. Praktisch!
Es gibt frühere Artikel über Qiita und Artikel über Boost :: python auf externen Websites. Es gab keinen Artikel, in dem erklärt wurde, woran ich festhielt oder wie man den sogenannten modernen cmake verwendet, wie in [diesem Artikel] erwähnt (https://qiita.com/shohirose/items/5b406f060cd5557814e9). Also habe ich diesen Artikel gemacht.
Boost.NumPy-Tutorial zum Erweitern von Python in C ++ (Übung) Dieser Artikel verwendet Boost-Numpy, aber Boost-Numpy wurde in Boost :: Python integriert und ist jetzt veraltet.
Erstellen Sie eine Bibliothek für Python in C ++ Übergeben von Numpy-Arrays zwischen Python und C ++ Diese Artikel waren auch sehr hilfreich.
Recommended Posts