使用Boost Python传递C++变量引用至Python时遇报错问题
解决Boost Python传递numpy数组实现原地修改的问题
问题分析
你当前的Python代码中x = 2*x是创建了一个新的numpy数组并重新赋值给变量x,并没有修改原数组的底层数据。另外,直接用boost::ref包装np::ndarray会报错,是因为Boost Python的numpy扩展没有为boost::python::numpy::ndarray类型注册对应的引用转换器,而且实际上你根本不需要用boost::ref——np::ndarray本身就是引用语义的对象,传递它的时候不会拷贝底层的内存数据,只是传递对象的引用。
解决方案
分两步修改代码:
1. 修改Python代码为原地操作
把pytest.py中的bar方法改成原地修改数组内容的逻辑,这样才能改变原数组的数据:
class Foo: def bar(self, x): print(x) x[:] = 2*x # 原地修改数组内容,而非创建新数组
2. C++代码无需使用boost::ref
保持原C++代码中的调用方式即可,因为np::ndarray传递时不会拷贝底层数据。原代码中的start_class.attr("bar")(np_arr);已经是高效的引用传递,底层数组内存不会被拷贝。
修改后运行代码,输出会变为:
[ 2 4 6 8 10] [ 4 8 12 16 20]
为什么boost::ref会报错?
Boost Python需要为每个C++类型注册对应的转换器,才能将boost::ref<T>包装的对象转换为Python对象。而Boost Numpy扩展并没有为np::ndarray注册boost::ref的转换器,所以直接使用boost::ref(np_arr)会触发类型转换错误。但这个操作完全没必要,因为np::ndarray本身的传递就是引用语义,不会产生昂贵的数据拷贝。
内容的提问来源于stack exchange,提问作者Hufh294
相关产品推荐
相关产品推荐

