I recently came across (thanks to Nicolas D.) a great library called PyBind that originally was a condensed part of Boost dealing with Python interfacing.
It allows to bind C++ and Python in many ways, relies heavily on meta-programmation (it is headers-only). With it, it’s very simple to pass Numpy arrays from Python to C++ and inversely dynamically create arrays in C++ and pass them to Python. You can install it with python-pip.
Here is a simple example of a C++ function accepting two Numpy arrays and returning the sum of both arrays in a Numpy array of the same shape.
For this dummy example, only 2-dimensionnal arrays are accepted but extending to more is trivial.
The C++ code, in a file called “example.cpp”, goes as follows (you can find all the code and instructions on my github page)
#include <pybind11/pybind11.h> #include <pybind11/numpy.h> namespace py = pybind11; py::array_t<double> add_arrays(py::array_t<double> input1, py::array_t<double> input2) { /* read input arrays buffer_info */ py::buffer_info buf1 = input1.request(), buf2 = input2.request(); if (buf1.size != buf2.size) throw std::runtime_error("Input shapes must match"); /* allocate the output buffer */ py::array_t<double> result = py::array_t<double>(buf1.size); py::buffer_info buf3 = result.request(); double *ptr1 = (double *) buf1.ptr, *ptr2 = (double *) buf2.ptr, *ptr3 = (double *)buf3.ptr; size_t X = buf1.shape[0]; size_t Y = buf1.shape[1]; /* Add both arrays */ for (size_t idx = 0; idx < X; idx++) for (size_t idy = 0; idy < Y; idy++) ptr3[idx*Y + idy] = ptr1[idx*Y+ idy] + ptr2[idx*Y+ idy]; /* Reshape result to have same shape as input */ result.resize({X,Y}); return result; } PYBIND11_MODULE(example, m) { m.doc() = "Add two vectors using pybind11"; // optional module docstring m.def("add_arrays", &add_arrays, "Add two NumPy arrays"); }
To compile it I used
c++ -O3 -Wall -shared -std=c++11 -fPIC -I/usr/include/python2.7 -lpython2.7 `python -m pybind11 --includes` example.cpp -o example`python-config --extension-suffix`
And call it from Python with:
import numpy as np import example a = np.zeros((10,3)) b = np.ones((10,3)) * 3 c = example.add_arrays(a, b) print c
That’s is, there’s no tiring data passing hassle, as I had to do when doing similar stuff manually.
Thanks Remy for spotting the mistakes in the html code removing <double> types.
Recent Comments