Use C ++ functions from python with pybind11

This article

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.

What is pybind11

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.

Difference from 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 Eigen and Numpy

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.

Installation

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.

Simple example

Let's use the addition function created in C ++ from Python. Same as the one in the official documentation.

C ++ source code

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

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

Run from python

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 ++.

Cooperation with Numpy

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.

Difficulty

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.

end

pybind11 It's convenient, so let's use it.

Recommended Posts

Use C ++ functions from python with pybind11
Wrap C ++ with Cython for use from Python
Call C from Python with DragonFFI
Execute C ++ functions from Python with Pybind11 (for Windows & Visual Studio Code people) Debugging
Use Python and MeCab with Azure Functions
Pass a list by reference from Python to C ++ with pybind11
Execute C ++ functions from Python with Pybind11 (for Windows & Visual Studio Code people) Environment construction
Use thingsspeak from python
[Python] Use JSON with Python
Use fluentd from python
Use MySQL from Python
Use mecab with Python3
Use DynamoDB with Python
Use python with docker
Use MySQL from Python
Use mecab-ipadic-neologd from python
Curry arbitrary functions with Python ....
Getting Started with Python Functions
Use Trello API with python
ABC163 C problem with python3
Use TUN / TAP with Python
Try embedding Python in a C ++ program with pybind11
Study from Python Hour3: Functions
Build an environment to execute C ++ functions from Python with Pybind11 (for Windows & Visual Studio Code people)
Use subsonic API with python3
ABC188 C problem with python3
With skype, notify with skype from python!
Use e-Stat API from Python
ABC187 C problem with python
Call C language functions from Python to exchange multidimensional arrays
Embed a Python interpreter into a C ++ app with pybind11 + cmake
Solve ABC163 A ~ C with Python
Python: How to use async with
Use Stanford Core NLP from Python
Use PointGrey camera with Python (PyCapture2)
Use vl53l0x with Raspberry Pi (python)
Using Rstan from Python with PypeR
Install Python from source with Ansible
Create folders from '01' to '12' with python
[Python] Use Basic/Digest authentication with Flask
Call popcount from Ruby / Python / C #
Use NAIF SPICE TOOLKIT with Python
Read and use Python files from Python
Forcibly use Google Translate from python
Use rospy with virtualenv in Python3
Free from hard-coding functions with SymPy
Solve ABC168 A ~ C with Python
Run Aprili from Python with Orange
Use kabu StationĀ® API from Python
10 functions of "language with battery" python
Tips for calling Python from C
Execute Python code from C # GUI
Use Python in pyenv with NeoVim
Use the Flickr API from Python
How to use FTP with Python
Use Windows 10 speech synthesis with Python
Solved AtCoder ABC 114 C-755 with Python3
Solve ABC162 A ~ C with Python
Run Python scripts synchronously from C #
Solve ABC167 A ~ C with Python
Call python from nim with Nimpy