簡體   English   中英

如何使用 boost/python 將 C++ 虛函數公開給 python?

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

編輯:使構造函數和析構函數虛擬並沒有幫助

根據boost/python 文檔,我可以通過在其周圍添加一個包裝器來公開一個虛擬 function。 這是他們在此處復制粘貼的示例:

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

這是我的 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);
}

它給出了這個我不太理解的長錯誤。

/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

最初我認為這與私有 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

我怎樣才能解決這個問題?

謝謝

為了匹配示例並構建沒有任何錯誤,您需要將class更改為struct用於包裝器,因為 Boost 使用 struct 來布局 memory。 此外,您還需要在包裝器中明確定義您的自定義構造函數。 最后,將行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