C++ Python与签名左值不匹配
我有一个类C++ Python与签名左值不匹配,c++,boost-python,C++,Boost Python,我有一个类Foo,其中有一个成员x,我想公开它,但是通过一个getter函数而不是属性。我刚发现,所以我想试试: #include <boost/python.hpp> namespace py = boost::python; struct Base { int x; }; struct Foo : Base { Foo(int i): Base{i} { } }; BOOST_PYTHON_MODULE(Foo) { py::class_&l
Foo
,其中有一个成员x
,我想公开它,但是通过一个getter函数而不是属性。我刚发现,所以我想试试:
#include <boost/python.hpp>
namespace py = boost::python;
struct Base {
int x;
};
struct Foo : Base {
Foo(int i): Base{i} { }
};
BOOST_PYTHON_MODULE(Foo)
{
py::class_<Foo>("Foo", py::init<int>())
.def_readonly("x", &Foo::x)
.def("getX", py::make_getter(&Foo::x))
;
}
#包括
名称空间py=boost::python;
结构基{
int x;
};
结构Foo:Base{
Foo(inti):基{i}{}
};
BOOST_PYTHON_模块(Foo)
{
py::class_u2;(“Foo”,py::init())
.def_只读(“x”,&Foo::x)
.def(“getX”,py::make_getter(&Foo::x))
;
}
然而,这并不能:
>>> import Foo
>>> f = Foo.Foo(42)
>>> f.x
42
>>> f.getX()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
Foo.getX(Foo)
did not match C++ signature:
getX(Base {lvalue})
>>>
导入Foo
>>>f=Foo.Foo(42)
>>>f.x
42
>>>f.getX()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
ArgumentError:中的Python参数类型
Foo.getX(Foo)
与C++签名不匹配:
getX(基{lvalue})
>>>
这个错误到底意味着什么?很明显,签名是匹配的!我怎样才能解决这个问题 问题是,如果仔细检查
ArgumentError
异常,则使用Foo
调用getX()
:
>>> f.getX()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
Foo.getX(Foo)
Python需要执行从左值Foo
到左值Base
的转换,而实际上您还没有告诉Boost它可以做到这一点。问题最终源于这样一个事实,即&Base::x
是int Base::*
而不是int Foo::*
,因此boost::python::make_getter
中的模板推导生成了一个函数,它采用Base
而不是Foo
最简单的解决方案是确保将指向成员的正确指针传递给make_getter
:
BOOST_PYTHON_MODULE(Foo)
{
py::class_<Foo>("Foo", py::init<int>())
.def_readonly("x", &Foo::x)
.def("getX", py::make_getter(static_cast<int Foo::*>(&Foo::x)))
;
}
不过这有点乏味,因此您可以编写一个快速的方法/宏来为您执行此操作:
template <typename Derived, typename Base, typename T>
T Derived::* as_derived(T Base::*member) {
return static_cast<T Derived::*>(member);
}
#define AS_DERIVED(CLS, FIELD) as_derived<CLS>(&CLS::FIELD)
模板
T派生::*as_派生(T基::*成员){
返回静态_cast(成员);
}
#定义为_派生(CLS,FIELD)为_派生(&CLS::FIELD)
您可以使用它:
BOOST_PYTHON_MODULE(Foo)
{
py::class_<Foo>("Foo", py::init<int>())
.def_readonly("x", &Foo::x)
.def("getX", py::make_getter(AS_DERIVED(Foo, x)))
;
}
BOOST\u PYTHON\u模块(Foo)
{
py::class_u2;(“Foo”,py::init())
.def_只读(“x”,&Foo::x)
.def(“getX”,py::make_getter(作为_派生的(Foo,x)))
;
}
或者,您可以直接告诉Boost.Python层次结构:
BOOST_PYTHON_MODULE(Foo)
{
py::class_<Base>("Base", py::no_init)
.def("getX", py::make_getter(&Base::x))
;
py::class_<Foo, py::bases<Base>>("Foo", py::init<int>())
.def_readonly("x", &Foo::x)
;
}
BOOST\u PYTHON\u模块(Foo)
{
py::class_u(“Base”,py::no_init)
.def(“getX”,py::make_getter(&Base::x))
;
py::class_u2;(“Foo”,py::init())
.def_只读(“x”,&Foo::x)
;
}
这样,Foo
继承了getX()
,一切都很好
BOOST_PYTHON_MODULE(Foo)
{
py::class_<Foo>("Foo", py::init<int>())
.def_readonly("x", &Foo::x)
.def("getX", py::make_getter(AS_DERIVED(Foo, x)))
;
}
BOOST_PYTHON_MODULE(Foo)
{
py::class_<Base>("Base", py::no_init)
.def("getX", py::make_getter(&Base::x))
;
py::class_<Foo, py::bases<Base>>("Foo", py::init<int>())
.def_readonly("x", &Foo::x)
;
}