Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I need to pass a numpy array to a python function from C++. The code is below. The python side:

import numpy as np
import  convert as cv

def f(x):
  x[0] = 5.
  return len(x)

if __name__ == '__main__':
  y = np.array([1., 2., 3., 4.])
  x = cv.func_n(f, y)
  print x

The C++ side:

#include <iostream>
#include <boost/python.hpp>

using namespace boost::python;
double func_n(PyObject* f, numeric::array &x)
{
  std::cerr << "Inside func_n\n";
  return boost::python::call<double>(f, boost::ref(x));
}

BOOST_PYTHON_MODULE(convert)
{
  numeric::array::set_module_and_type("numpy", "ndarray");

  def("func_n", &func_n);

}

What the C++ code is supposed to do is to take a python functopn and a numpy array as two arguments and then pass the numpy array to the python function. The error I an getting is:

Traceback (most recent call last):
  File "mm.py", line 11, in <module>
    x = cv.func_n(f, y)
TypeError: No Python class registered for C++ class class boost::python::numeric::array

Why? Do I have to register the module during the recursive call of the interpreter and, if so, how?

share|improve this question
 
Continuation: using return boost::python::call<double>(f, x); instead of return boost::python::call<double>(f, boost::ref(x)); helps and the code works fine. What does boost::ref(x) do? I as under the impression that boost::python::call copies the arguments. Turned out it doesn't. Where can this be clarified? –  user1666241 Oct 22 '12 at 22:37

1 Answer

boost::ref(x) returns a boost::reference_wrapper<T>, which allows you to pass references to by-value functions.

The boost::python::call docs show that arguments are treated differently based on their type. If the arg is a boost::reference_wrapper<T>, it effectively passes a reference to x down to Python.

So, in the code above, you were passing the reference to your numeric::array to Python. The function you're calling from Python also accepts a reference.

Now I'm not sure about this, but I suspect that since you were never actually passing a numeric::array between Python/C++, boost::python decided not to wrap it or create converters (since you're really just passing around addresses). This may be why you saw no Python class registered for the numeric::array type.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.