I am trying to pass an argument by reference to a Python function from C++ using the Boost Python library (as well as the Boost Numpy extension). The object in question is an ndarray, and passing it by value works just fine as demonstrated below:
#include <boost/python/numpy.hpp>
#include <cstdlib>
#include <iostream>
#include <array>
namespace p = boost::python;
namespace np = boost::python::numpy;
int main(int argc, char* argv[]) {
// Set PYTHONPATH
setenv("PYTHONPATH", ".", 1);
// Initialize Python
Py_Initialize();
// Initialize Numpy
np::initialize();
// Create array of 5 integers
std::array<int,5> arr = { 2,4,6,8,10};
// Create Numpy array of ints.
p::tuple shape = p::make_tuple(5);
np::dtype dtype = np::dtype::get_builtin<int>();
np::ndarray np_arr = np::from_data(arr.data(),
dtype,
shape,
p::make_tuple(sizeof(int)),
p::object());
try {
// Import Python module.
p::object python_module =
p::import("pytest");
// Pull class from module.
p::object start_class = python_module.attr("Foo")();
// Call class function with argument
start_class.attr("bar")(np_arr);
// Call function again
start_class.attr("bar")(np_arr);
}
catch (const boost::python::error_already_set&) {
// Print Python Errors
PyErr_Print();
}
return 0;
}
The relevant pytest.py
file is as follows:
class Foo:
def bar(self, x):
print(x)
x = 2*x
This prints out [ 2 4 6 8 10] [ 2 4 6 8 10]
as expected. However, I would like for the ndarray to be passed by reference in order to avoid any expensive copies (i.e. the output would be [ 2 4 6 8 10] [ 4 8 12 16 20]
).
According to the documentation, the way to do this seems to be through boost::ref
. However, when I wrap the argument as a reference (by changing the function call to start_class.attr("bar")(boost::ref(np_arr));
) I get the following error message from Python: TypeError: No Python class registered for C++ class boost::python::numpy::ndarray