简体   繁体   English

如何使用 boost/python 将 C++ 虚函数公开给 python?

[英]How to expose C++ virtual functions to python using boost/python?

Edit: making the constructor and destructor virtual didn't help编辑:使构造函数和析构函数虚拟并没有帮助

According to the boost/python documentation , I can expose a virtual function by having a wrapper around it.根据boost/python 文档,我可以通过在其周围添加一个包装器来公开一个虚拟 function。 Here's their example copy-pasted here:这是他们在此处复制粘贴的示例:

// base class
struct Base
{
    virtual ~Base() {}
    virtual int f() { return 0; }
};
// wrapper for the base function
struct BaseWrap : Base, wrapper<Base>
{
    int f()
    {
        if (override f = this->get_override("f"))
            return f(); // *note*
        return Base::f();
    }

    int default_f() { return this->Base::f(); }
};

// exposing the class
class_<BaseWrap, boost::noncopyable>("Base")
    .def("f", &Base::f, &BaseWrap::default_f);

Here's my cpp file with the minimal amount of code needed to replicate the error:这是我的 cpp 文件,其中包含复制错误所需的最少代码:

#include <iostream>
#include <python3.6m/Python.h>
#include <boost169/boost/python.hpp>
#include <boost169/boost/python/make_constructor.hpp>
#include <boost169/boost/python/detail/api_placeholder.hpp>
using namespace boost::python;
class BaseNode{
public:
    BaseNode(boost::python::object position);
    ~BaseNode();
    boost::python::object _position;
    virtual int test(){
        return 10;
    }
};

class BaseNodeVirtual:BaseNode, boost::python::wrapper<BaseNode>{
public:
    int test(){
        if (override test = this->get_override("test"))
            return test();
        return BaseNode::test();
    }
    int default_test(){
        return this->BaseNode::test();
    }
};

// pickle support for BaseNode
struct BaseNode_pickle_suite : boost::python::pickle_suite{
    static boost::python::tuple getinitargs(BaseNode const& baseNode){
        return boost::python::make_tuple(baseNode._position);
    }
    static boost::python::tuple getstate(boost::python::object obj)
    {
        BaseNode& baseNode = boost::python::extract<BaseNode&>(obj);
        return boost::python::make_tuple(obj.attr("__dict__"));
    }

    static void setstate(boost::python::object obj, boost::python::tuple state)
    {
        BaseNode& baseNode = boost::python::extract<BaseNode&>(obj);
        boost::python::dict d = extract<dict>(obj.attr("__dict__"));
        d.update(state[0]);

    }
    static bool getstate_manages_dict() { return true; }

};

BaseNode::BaseNode(boost::python::object position){
    this->_position = position;
}

BaseNode::~BaseNode(){

}


BOOST_PYTHON_MODULE(BaseNode){
    class_<BaseNodeVirtual, bases<BaseNode,boost::python::wrapper<BaseNode>>>("BaseNode", init<boost::python::object>())
    .def_readwrite("_position", &BaseNode::_position)
    .def_pickle(BaseNode_pickle_suite())
    .def("test", &BaseNode::test, &BaseNodeVirtual::default_test);
}

and it gives this long error that I don't quite understand.它给出了这个我不太理解的长错误。

/usr/include/boost169/boost/python/object/value_holder.hpp:133:13: note: candidates are:
minNode.cpp:17:7: note: BaseNodeVirtual::BaseNodeVirtual(const BaseNodeVirtual&)
 class BaseNodeVirtual: BaseNode, boost::python::wrapper<BaseNode>{
       ^
minNode.cpp:17:7: note:   no known conversion for argument 1 from ‘const boost::python::api::object’ to ‘const BaseNodeVirtual&’
minNode.cpp:17:7: note: BaseNodeVirtual::BaseNodeVirtual(BaseNodeVirtual&&)
minNode.cpp:17:7: note:   no known conversion for argument 1 from ‘const boost::python::api::object’ to ‘BaseNodeVirtual&&’
In file included from /usr/include/boost169/boost/preprocessor/iteration/detail/iter/forward1.hpp:52:0,
                 from /usr/include/boost169/boost/python/object/value_holder.hpp:46,
                 from /usr/include/boost169/boost/python/object/class_metadata.hpp:14,
                 from /usr/include/boost169/boost/python/class.hpp:23,
                 from /usr/include/boost169/boost/python.hpp:18,
                 from minNode.cpp:3:
/usr/include/boost169/boost/python/object/value_holder.hpp:135:80: erreur: ‘boost::python::detail::wrapper_base’ is an inaccessible base of ‘BaseNodeVirtual’
     {
                                                                                ^
make: *** [minNode.o] Erreur 1

Initially I thought that this has something to do with the private inheritance (since according to this post and this post this is a problem that comes with protected and private inheritance), so I tried changing the inheritance to public instead, but it still gave me an error (with both base classes as public and not having boost::python::wrapper specified in bases):最初我认为这与私有 inheritance 有关(因为根据这篇文章这篇文章,这是受保护和私有继承带来的问题),所以我尝试将 inheritance 改为公共,但它仍然给了我一个错误(两个基类都是公共的,并且没有在 bases 中指定 boost::python::wrapper):


/usr/include/boost169/boost/python/object/value_holder.hpp:133:13: erreur: no matching function for call to ‘BaseNodeVirtual::BaseNodeVirtual(boost::reference_wrapper<const BaseNode>::type&)’
             BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil)
             ^
/usr/include/boost169/boost/python/object/value_holder.hpp:133:13: note: candidates are:
minNode.cpp:17:7: note: BaseNodeVirtual::BaseNodeVirtual(const BaseNodeVirtual&)
 class BaseNodeVirtual:public BaseNode, public boost::python::wrapper<BaseNode>{
       ^
minNode.cpp:17:7: note:   no known conversion for argument 1 from ‘boost::reference_wrapper<const BaseNode>::type {aka const BaseNode}’ to ‘const BaseNodeVirtual&’
minNode.cpp:17:7: note: BaseNodeVirtual::BaseNodeVirtual(BaseNodeVirtual&&)
minNode.cpp:17:7: note:   no known conversion for argument 1 from ‘boost::reference_wrapper<const BaseNode>::type {aka const BaseNode}’ to ‘BaseNodeVirtual&&’
make: *** [minNode.o] Erreur 1

How can I fix this?我怎样才能解决这个问题?

Thanks谢谢

To match the example and build without any errors, you will need to change class to struct for the wrapper because Boost uses struct to layout memory.为了匹配示例并构建没有任何错误,您需要将class更改为struct用于包装器,因为 Boost 使用 struct 来布局 memory。 Also you will need to explicitly define your custom constructor in the wrapper.此外,您还需要在包装器中明确定义您的自定义构造函数。 Lastly, change the line bases(...) to boost::noncopyable :最后,将行bases(...)更改为boost::noncopyable

#include <iostream>
#include <python3.6m/Python.h>
#include <boost169/boost/python.hpp>
#include <boost169/boost/python/make_constructor.hpp>
#include <boost169/boost/python/detail/api_placeholder.hpp>
using namespace boost::python;
class BaseNode{
public:
    BaseNode(boost::python::object position);
    ~BaseNode();
    boost::python::object _position;
    virtual int test(){ return 10; }
};

BaseNode::BaseNode(boost::python::object position){
    this->_position = position;
}

BaseNode::~BaseNode(){

}

// pickle support for BaseNode
struct BaseNode_pickle_suite : boost::python::pickle_suite{
    static boost::python::tuple getinitargs(BaseNode const& baseNode){
        return boost::python::make_tuple(baseNode._position);
    }
    static boost::python::tuple getstate(boost::python::object obj)
    {
        BaseNode& baseNode = boost::python::extract<BaseNode&>(obj);
        return boost::python::make_tuple(obj.attr("__dict__"));
    }

    static void setstate(boost::python::object obj, boost::python::tuple state)
    {
        BaseNode& baseNode = boost::python::extract<BaseNode&>(obj);
        boost::python::dict d = extract<dict>(obj.attr("__dict__"));
        d.update(state[0]);

    }
    static bool getstate_manages_dict() { return true; }

};

struct BaseNodeVirtual : BaseNode, boost::python::wrapper<BaseNode> {
    BaseNodeVirtual(boost::python::object position) : BaseNode(position) {}
    int test(){
        if (override test = this->get_override("test"))
            return test();
        return BaseNode::test();
    }
    int default_test(){
        return this->BaseNode::test();
    }
};

int main() {

}

BOOST_PYTHON_MODULE(example){
    // exposing the class
    class_<BaseNodeVirtual, boost::noncopyable>("BaseNode", init<boost::python::object>())
        .def_readwrite("_position", &BaseNode::_position)
        .def_pickle(BaseNode_pickle_suite())
        .def("test", &BaseNode::test, &BaseNodeVirtual::default_test);

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM