我有以下类(class):
#include <array>
template<unsigned short D>
class Point {
private:
std::array<float, D> coordinates;
public:
Point() { for(int i=D-1; i>=0; --i) coordinates[i] = 0.0; }
Point(const Point& rhs) = default;
Point& operator=(const Point& rhs) = default;
~Point() = default;
float& get_ref(const unsigned short dimension)
{ return coordinates[dimension-1]; }
};
我正在尝试将其包裹起来:
#include <boost/python.hpp>
BOOST_PYTHON_MODULE(fernpy) {
using namespace boost::python;
class_< Point<2> >("point")
.def("__call__", &Point<2>::get_ref, return_internal_reference<>());
}
我正在使用 gcc-4.7 为 Fedora 17 上的 boost 1.48 和 python-2.7 编译。所有代码都是一个名为 testpy.cpp 的文件。我正在使用这些命令进行编译:
g++ -std=c++11 -g -fPIC -I/usr/include/python2.7 -c testpy.cpp
g++ -shared -g -lpython2.7 -lboost_python -o libfern.so testpy.o
编译器返回一堆 boost 内部错误,太多了,无法在此处发布。这段摘录似乎是它的核心。前面有一堆“required from”,后面有“note”。
/usr/include/boost/python/object/make_instance.hpp:27:9: error: no matching function for call to ‘assertion_failed(mpl_::failed************ boost::mpl::or_<boost::is_class<float>, boost::is_union<float>, mpl_::bool_<false>, mpl_::bool_<false>, mpl_::bool_<false> >::************)’
如果我从 get_ref 返回一个普通的 float 并从包装器的 .def 行中删除 return_internal_reference<>() 参数,它就可以正常工作。这很奇怪,因为我正在用另一个更复杂的类模板做同样的事情,而且它在那里也工作得很好。我已经用谷歌搜索了将近一整天的时间来反对这个问题。任何人都知道到底发生了什么?
更新:
我最终使用了 python 中的“getitem”和“setitem”特殊方法,a la this link .该链接展示了如何使用用于访问函数的静态包装器定义漂亮的结构模板,这样您就不必弄乱原始 C++ 类的接口(interface)。
最佳答案
从 python 的角度来看,floats
是一种不可变类型。因此,python 不允许更改该值。
例如在python中出现如下情况:
coordinates = [ 5, 10, 15 ]
x = cooardinates[ 2 ] # Bind x to refer to the int(15) object.
x = 5 # Rebind x to refer to the int(5) object.
# Does not modify coordinates.
现在,考虑以下几点:
from fernpy import point
p = point()
x = p(2) # Bind x to refer to the float(p(2)) object.
x = 5 # Rebind x to refer to the int(5) object.
# Does not set p.coordinates[2] to 5.
因此,boost::python
阻止返回对 python 中不可变类型的引用,因为 Python 不支持它。 x
不存储值 5
;相反,它包含对 5
对象的引用。如果分配给 x
没有重新绑定(bind) x
,则可能会出现无意义的语句,例如 6 = 5
。
编译错误是一种静态检查,它限制 return_internal_reference
仅适用于类或 union ,因为它们在 Python 中是可变类型。我想,起作用的“更复杂的类模板”正在返回对用户类型的引用。
关于c++ - 使用 boost.python 返回内部引用的间歇性错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11143634/