### Pybind Numpy访问2D / ND阵列

#### [英]Pybind Numpy access 2D / ND arrays

New to pybind - read the documentation but I do not grasp how to apply it to 2D arrays.

pybind新手 - 阅读文档,但我不知道如何将其应用于2D数组。

I have two arrays storing 3d coordinates `shape = (10,3)`

``````a = np.zeros(shape=(10,3))
b = np.ones(shape=(10,3)) * 3
c = a + b
``````

Now, using pybind, how do I perform this operation in C++ working on the numpy arrays?

In some documentations I read to access the elements with the `[]` operator, in others with `()`. How do assign the 3D vector? How would I get the pointer to the array element to use strides for assignment - or does it have an operator?

## 2 个解决方案

### #1

3

PyBind is awesome, shout out to the authors/maintainers! You have an almost working example here.

PyBind真棒,向作者/维护者大喊大叫!你这里有一个近乎有效的例子。

Adapted to your problem it would give something like (edited answer after El Dude's comment):

``````#include <iostream>
#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) {
auto buf1 = input1.request(), buf2 = input2.request();

if (buf1.size != buf2.size)
throw std::runtime_error("Input shapes must match");

/*  allocate the buffer */
py::array_t<double> result = py::array_t<double>(buf1.size);

auto buf3 = result.request();

double *ptr1 = (double *) buf1.ptr,
*ptr2 = (double *) buf2.ptr,
*ptr3 = (double *) buf3.ptr;
int X = buf1.shape;
int Y = buf1.shape;

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 array to match input shape
result.resize({X,Y});

return result;
}

PYBIND11_MODULE(example, m) {
m.doc() = "Add two vectors using pybind11"; // optional module docstring

}
``````

That I built on linux with python2.7 and gcc v5.4 using (I had to use a slightly different command than provided in the doc, because Python.h wasn't found, hence I added the link to python 2.7)

``````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 you'd call it from python with

``````import numpy as np
import example # [bad] name I chose for my compiled module

a = np.zeros((10,3))
b = np.ones((10,3)) * 3
c = example.add_arrays(a, b)

print c
``````

Hope it helps.

### #2

0

The trick is to use the buffer class. It's well hidden / convoluted into the documentation and examples, but it's mentioned (@Christian 's post).

Buffers contain a pointer to the data as well as strides and others array parameters. Essentially the numpy header accessed through `request` method. Easy to use from there on, but finding it is bit of a pain since the example uses beautiful `C11` `auto` type to explain this usage.