Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Python与签名左值不匹配_C++_Boost Python - Fatal编程技术网

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)
        ;
}