受python保护的析构函数问题 名称空间测试 { 班级活动 { 公众: 枚举类型{BEGIN=0,RESULT,END}; 类型get_Type()const{return m_Type;} 受保护的: 事件(){} ~Event(){} m_型; }; 类EventBegin:公共事件 { 公众: EventBegin(){m_type=Event::BEGIN;} ~EventBegin(){} }; 类EventResult:公共事件 { 公众: EventResult(int-result){m_-type=Event::result;m_-result=result;} ~EventResult(){} int get_result(){return m_result;} 受保护的: int m_结果; }; 类EventEnd:公共事件 { 公众: EventEnd(){m_type=Event::END;} ~EventEnd(){} }; 类EventListener { 公众: 事件上的虚拟无效(常量事件和事件)=0; }; 结构EventListenerWrap:EventListener,py::wrapper { 无效的 on_事件(常量事件和事件) { 此->获取覆盖(“在事件上”)(事件); } }; BOOST_PYTHON_模块(test_py) { { py::scope outer=py::class_u(“Event”,py::no\u init) .add_属性(“事件类型”和事件::get_类型); py::enum_uzy(“EventType”) .value(“开始”,事件::开始) .value(“结果”,事件::结果) .value(“结束”,事件::结束) .export_值(); } { py::class_u(“EventBegin”); } { py::class_u(“EventResult”,py::no_init) .def(py::init((py::arg(“结果”)) .add_属性(“result”、&EventResult::get_result); } { py::class_u(“EventEnd”); } { py::类(“EventListener”,py::no_init) .def(“on_事件”,py::pure_虚拟(&EventListener::on_事件)); } } }

受python保护的析构函数问题 名称空间测试 { 班级活动 { 公众: 枚举类型{BEGIN=0,RESULT,END}; 类型get_Type()const{return m_Type;} 受保护的: 事件(){} ~Event(){} m_型; }; 类EventBegin:公共事件 { 公众: EventBegin(){m_type=Event::BEGIN;} ~EventBegin(){} }; 类EventResult:公共事件 { 公众: EventResult(int-result){m_-type=Event::result;m_-result=result;} ~EventResult(){} int get_result(){return m_result;} 受保护的: int m_结果; }; 类EventEnd:公共事件 { 公众: EventEnd(){m_type=Event::END;} ~EventEnd(){} }; 类EventListener { 公众: 事件上的虚拟无效(常量事件和事件)=0; }; 结构EventListenerWrap:EventListener,py::wrapper { 无效的 on_事件(常量事件和事件) { 此->获取覆盖(“在事件上”)(事件); } }; BOOST_PYTHON_模块(test_py) { { py::scope outer=py::class_u(“Event”,py::no\u init) .add_属性(“事件类型”和事件::get_类型); py::enum_uzy(“EventType”) .value(“开始”,事件::开始) .value(“结果”,事件::结果) .value(“结束”,事件::结束) .export_值(); } { py::class_u(“EventBegin”); } { py::class_u(“EventResult”,py::no_init) .def(py::init((py::arg(“结果”)) .add_属性(“result”、&EventResult::get_result); } { py::class_u(“EventEnd”); } { py::类(“EventListener”,py::no_init) .def(“on_事件”,py::pure_虚拟(&EventListener::on_事件)); } } },python,c++,python-2.7,boost,boost-python,Python,C++,Python 2.7,Boost,Boost Python,我在事件基类中有一个受保护的构造函数和析构函数,不能更改它。 在Python 2.7中,我需要从EnviistListNER类派生,并将指针发送回C++代码。 在编译过程中,我遇到了如下错误: namespace test_py { class Event { public: enum Type { BEGIN = 0, RESULT, END }; Type get_type( ) const { return m_type; } protected: Event

我在事件基类中有一个受保护的构造函数和析构函数,不能更改它。 在Python 2.7中,我需要从EnviistListNER类派生,并将指针发送回C++代码。 在编译过程中,我遇到了如下错误:

namespace test_py
{

class Event
{
public:
    enum Type { BEGIN = 0, RESULT, END };

    Type get_type( ) const { return m_type; }

protected:
    Event( ) { }
    ~Event( ) { }
    Type m_type;
};

class EventBegin : public Event
{
public:
    EventBegin( ) { m_type = Event::BEGIN; }
    ~EventBegin( ) {}
};

class EventResult : public Event
{
public:
    EventResult( int result ) { m_type = Event::RESULT; m_result = result; }
    ~EventResult( ) {}
    int get_result( ) { return m_result; }

protected:
    int m_result;
};

class EventEnd : public Event
{
public:
    EventEnd( ) { m_type = Event::END; }
    ~EventEnd( ) {}
};

class EventListener
{
public:
    virtual void on_event( const Event& event ) = 0;
};


struct EventListenerWrap: EventListener, py::wrapper< EventListener >
{
    void
    on_event( const Event& event )
    {
        this->get_override( "on_event" )( event );
    }
};

BOOST_PYTHON_MODULE( test_py )
{
    {
        py::scope outer = py::class_< Event, boost::noncopyable >( "Event", py::no_init )
            .add_property( "event_type", &Event::get_type );

        py::enum_< Event::Type >( "EventType" )
            .value( "BEGIN", Event::BEGIN )
            .value( "RESULT", Event::RESULT )
            .value( "END", Event::END )
            .export_values( );
    }

    {
        py::class_< EventBegin, py::bases< Event > >( "EventBegin" );
    }

    {
        py::class_< EventResult, py::bases< Event > >( "EventResult", py::no_init )
            .def( py::init< int >( ( py::arg( "result" ) ) ) )
            .add_property( "result", &EventResult::get_result );
    }

    {
        py::class_< EventEnd, py::bases< Event > >( "EventEnd" );
    }

    {
        py::class_< EventListenerWrap, boost::noncopyable >( "EventListener", py::no_init )
            .def( "on_event", py::pure_virtual( &EventListener::on_event ) );
    }
}

}
/boost/python/detail/destroy.hpp:static void boost::python::detail::value_destrover::execute(const volatile T*)[with T=test_py::Event]的实例化中:
/boost/python/detail/destroy.hpp:95:36:来自“void boost::python::detail::destroy_referent_impl(void*,T&(*)())[with T=const test_py::Event]的必填项”
/boost/python/detail/destroy.hpp:101:39:来自“void boost::python::detail::destroy_referent(void*,T(*)())[with T=const test_py::Event&]的必填项
/boost/python/converter/rvalue_from_python_data.hpp:135:71:boost::python::converter::rvalue_from_python_data::~rvalue_from_python_data()
/boost/python/converter/arg_from_python.hpp:107:8:required from'PyObject*boost::python::detail::caller_arity::impl::operator()(PyObject*,PyObject*)[带F=void(test_py::EventListener::*)(const test_py::Event&);Policies=boost::python::default_调用策略;Sig=boost::mpl::vector3;PyObject='
/boost/python/object/py_function.hpp:38:33:必须来自“PyObject*boost::python::objects::caller\u py_function\u impl::operator()(PyObject*,PyObject*)[with caller=boost::python::detail::caller;PyObject=\u object]”
EventListener.cpp:193:1:此处为必填项
EventListener.cpp:18:5:错误:“test_py::Event::~Event()”受保护
~Event(){}
^
在/boost/python/converter/rvalue_from_python_data.hpp:10:0包含的文件中,
从/boost/python/converter/registry.hpp:9,
从/boost/python/converter/registed.hpp:8,
从/boost/python/object/make_instance.hpp:10,
从/boost/python/object/make_ptr_instance.hpp:8,
from/boost/python/to_python_indirect.hpp:11,
从/boost/python/converter/arg_到_python.hpp:10,
from/boost/python/call.hpp:15,
从/boost/python/object_core.hpp:14,
从/boost/python/object/class.hpp:9,
从/boost/python/class.hpp:13,
自.././defs.hpp:6,
从../defs.hpp:3,
从defs.hpp:3,
来自EventListener.cpp:1:
/boost/python/detail/destroy.hpp:33:9:错误:在此上下文中
p->~T();
^

公开函数时,Boost.Python将为每个参数生成转换器。对于类型为
T
T&
的参数,生成的Python转换器将保存对象的副本,因此需要访问副本构造函数和析构函数。此行为的基本原理是防止意外暴露悬空引用。将C++参数传递给Python时也是如此。

在以下情况下,此行为会出现问题:

  • EventListener::on_event(const event&)
    作为Boost公开。Python正在尝试创建一个对象,该对象将保存
    事件的副本。若要解决此问题,请考虑公开一个接受<代码>事件*/COD>的辅助函数,然后将其委托给原始函数。
  • EventListenerWrap::on_Event
    中将
    事件
    对象传递给Python。要解决这个问题,请考虑在<代码> Boo::ReF()/代码>或<代码> Boo::PtRo::/Trave> /Cult>
请注意,如果不创建副本,就有可能产生悬空引用。如果实际的<代码>事件< /C>对象是Python所拥有的,那么它的生存期至少需要和C++中的任何引用一样长。同样地如果实际的<代码>事件< /C>对象是C++所拥有的,那么它的生存期至少需要在Python中引用它的时间长。
struct EventListenerWrap
:EventListener,
boost::python::wrapper
{
事件无效(常量事件和事件)
{
这
/boost/python/detail/destroy.hpp: In instantiation of ‘static void boost::python::detail::value_destroyer<false>::execute(const volatile T*) [with T = test_py::Event]’:
/boost/python/detail/destroy.hpp:95:36:   required from ‘void boost::python::detail::destroy_referent_impl(void*, T& (*)()) [with T = const test_py::Event]’
/boost/python/detail/destroy.hpp:101:39:   required from ‘void boost::python::detail::destroy_referent(void*, T (*)()) [with T = const test_py::Event&]’
/boost/python/converter/rvalue_from_python_data.hpp:135:71:   required from ‘boost::python::converter::rvalue_from_python_data<T>::~rvalue_from_python_data() [with T = const test_py::Event&]’
/boost/python/converter/arg_from_python.hpp:107:8:   required from ‘PyObject* boost::python::detail::caller_arity<2u>::impl<F, Policies, Sig>::operator()(PyObject*, PyObject*) [with F = void (test_py::EventListener::*)(const test_py::Event&); Policies = boost::python::default_call_policies; Sig = boost::mpl::vector3<void, test_py::EventListener&, const test_py::Event&>; PyObject = _object]’
/boost/python/object/py_function.hpp:38:33:   required from ‘PyObject* boost::python::objects::caller_py_function_impl<Caller>::operator()(PyObject*, PyObject*) [with Caller = boost::python::detail::caller<void (test_py::EventListener::*)(const test_py::Event&), boost::python::default_call_policies, boost::mpl::vector3<void, test_py::EventListener&, const test_py::Event&> >; PyObject = _object]’
EventListener.cpp:193:1:   required from here
EventListener.cpp:18:5: error: ‘test_py::Event::~Event()’ is protected
     ~Event( ) { }
     ^
In file included from /boost/python/converter/rvalue_from_python_data.hpp:10:0,
                 from /boost/python/converter/registry.hpp:9,
                 from /boost/python/converter/registered.hpp:8,
                 from /boost/python/object/make_instance.hpp:10,
                 from /boost/python/object/make_ptr_instance.hpp:8,
                 from /boost/python/to_python_indirect.hpp:11,
                 from /boost/python/converter/arg_to_python.hpp:10,
                 from /boost/python/call.hpp:15,
                 from /boost/python/object_core.hpp:14,
                 from /boost/python/object/class.hpp:9,
                 from /boost/python/class.hpp:13,
                 from ../../defs.hpp:6,
                 from ../defs.hpp:3,
                 from defs.hpp:3,
                 from EventListener.cpp:1:
/boost/python/detail/destroy.hpp:33:9: error: within this context
         p->~T();
         ^
    py::scope outer = py::class_< Event, boost::noncopyable >( "Event", py::no_init )
        .add_property( "event_type", &Event::get_type );
#include <memory>
namespace test_py
{

    class Event
    {
    public:
        enum Type { BEGIN = 0, RESULT, END };

        Type get_type( ) const { return m_type; }

    protected:
        Event( ) { }
        ~Event( ) { }
        Type m_type;
    };

    class EventBegin : public Event
    {
    public:
        EventBegin( ) { m_type = Event::BEGIN; }
        ~EventBegin( ) {}
    };

    class EventResult : public Event
    {
    public:
        EventResult( int result ) { m_type = Event::RESULT; m_result = result; }
        ~EventResult( ) {}
        int get_result( ) { return m_result; }

    protected:
        int m_result;
    };

    class EventEnd : public Event
    {
    public:
        EventEnd( ) { m_type = Event::END; }
        ~EventEnd( ) {}
    };

    class EventProxy
    {
        // define an interface for turning a non-polymorphic event
        // into a polymorphic one
        struct concept
        {
            virtual const Event* as_event() const = 0;
            virtual ~concept() = default;
        };

        // define a model to support the polymorphic interface for a 
        // non-polymorphic concrete object
        template<class T> struct model : concept
        {
            template<class...Args> model(Args&&... args)
            : _event(std::forward<Args>(args)...)
            {}

            const Event* as_event() const override {
                return &_event;
            }

            T _event;
        };

        // construct the model that contains any Event
        template<class T>
        EventProxy(std::shared_ptr<T> ptr)
        : _impl(std::move(ptr))
        {}

    public:
        // T should be derived from Event...
        template<class T, class...Args>
        static EventProxy create(Args&&... args)
        {
            return EventProxy(std::make_shared<model<T>>(std::forward<Args>(args)...));
        }

        // simply return the address of the internal non-polymorphic event    
        const Event* as_event() const {
            return _impl->as_event();
        }

        // return a shared pointer that points to the internal Event BUT
        // defers lifetime ownership to our internal shared_ptr to 
        // our model. This means we never invoke the polymorphic
        // destructor of Event through the protected interface. 
        std::shared_ptr<const Event> as_shared_event() const {
            return std::shared_ptr<const Event>(_impl, _impl->as_event());
        }

    private:
        // lifetime of the proxy is owned by this shared_ptr.
        std::shared_ptr<concept> _impl;
    };

}

// a quick test.    
auto main() -> int
{
    auto ep = test_py::EventProxy::create<test_py::EventBegin>();

    const test_py::Event* p = ep.as_event();

    std::shared_ptr<const test_py::Event> sp = ep.as_shared_event();
}