Python Advent Calendar 2016 It's the 8th day.
I talked about pybind11 at this year's Boost. Study session, but I didn't touch on the specifics so much, so it's a supplement.
C ++ python bindings that can be used with C ++ 11 or later. You can publish a module created in C ++ to python. Recommended for those who want to use C ++ for time-consuming processing and python for various trials. *** There are limits to how well you can use Numpy, so there are some parts that you have to write in C ++. Recently, I wrote only the minimum I have to make in C ++, and the rest is style using scipy, scikit-image, etc. There are options such as Cython, but the C ++ source is still easier than chasing and debugging the automatically generated C code.
There are several Python and C ++ bindings, one of which is Boost.Python. This itself is useful as a function. I wrote about Boost.Python before. (However, the story of using Python from C ++)
One of the reasons why Python is often used in the scientific and technological computing area is the existence of Numpy, but there is a library that uses Boost.Python called Boost.Numpy, and if you use this, Numpy will be a C ++ function. It is very convenient because you can easily pass the data created in. This is also I wrote it before.
However, Boost.Python is annoying because it requires building a library. It may be misunderstood that Boost.Python can be used in both Python2 and Python3 series. However, in order to use it in Python2 series, you have to build 2 series, and in order to use it in Python3 series, you have to build 3 series. You also have to choose debug version, static linking or dynamic linking. Of course, Boost.Numpy also needs to be built.
Pybind11 is an alternative to such annoying Boost.Python.
--For C ++ 11 or later compilers --Can be used with Header-only
It cannot be used with compilers that do not support C ++ 11. Let's throw away such a compiler. Boost.Python is bloated because it works with older compilers, but pybind11 is small because it only targets C ++ 11 and above.
Boost.Python required a library build and was a hassle to install, but pybind11 is Header-only so you can use it right away. I think this advantage alone is a reason to move to pybind11.
Migrating from Boost.Python is relatively easy. If you can use C ++ 11, consider it now.
Cooperation with the C ++ matrix library Eigen and the Python array library Numpy has already been considered. You don't need to install Boost.Numpy separately like Boost.Python, and you don't need to build libraries.
Since it is Header-only, just clone or download it from github and put it in your favorite directory. You may be able to install it with the OS package manager, but it seems to be updated frequently, so I think you should get it from github. I have experienced that the version installed by the package manager is old and there is no function that should be in the latest version.
Let's use the addition function created in C ++ from Python. Same as the one in the official documentation.
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");
}
Since it is a shared library, there is no main function. The name specified by PYBIND11_PLUGIN is the module name. In other words, when using from Python, in this example it is import cppmod
.
The following `py :: module``` is a module description. The name and the so-called docstring. Next, specify the function to be published to python. The last
return m.ptr ()
`` was not needed in Boost.Python, but it should be added in pybind11.
For reference, in the case of Boost.Python
BOOST_PYTHON_MODULE(cppmod) {
Py_Initialize();
py::def("add",add);
}
It will be. It's almost the same.
Compile as a shared library (DLL for Windows, but with a .pyd extension). ~~ Since I use SCons, the configuration file looks like this: Please set according to the environment. By the way, SCons is a build tool for Python. It is said that a huge project is slow, but C ++ compilation itself is slow, so I use it without worrying about it. .. ~~ I decided to use cmake without going against the trend. Write something like the following 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)
The build command looks like this.
$ mkdir build && cd build
$ cmake ..
$ make
First, place the compiled shared library (eg `` `cppmod.cpython-36m-x86_64-linux-gnu.so```) in the directory where you want to run Python.
Then start Python and import it. First, let's issue help. It should look like this:
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
The module, function description (docstring), function arguments and return types, etc. are displayed.
Next, let's use the add function.
>>> cppmod.add(2,3)
5
I was able to call a function created in C ++.
Use the pybind11 / numpy.h
header. You can receive ndarray type data and pass it to Python with a class called py :: array_t.
#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");
}
Example of use
>>> 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.])
It's very easy.
I have documentation, but it seems that there is no reference for each function yet. It's okay if you look at the source code, but maybe only C ++ Chotdekir people have no problem.
pybind11 It's convenient, so let's use it.