Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
659 views
in Technique[技术] by (71.8m points)

python - Pybind Numpy access 2D / ND arrays

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

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

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) {
  py::buffer_info buf1 = input1.request();
  py::buffer_info 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);

  py::buffer_info buf3 = result.request();

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

  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

        m.def("add_arrays", &add_arrays, "Add two NumPy arrays");
}

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.


EDIT - I've created a github repository containing a few complete examples based on PyBind11 that should compile on all platforms.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...