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 ) );
}
}
}
我在事件基类中有一个受保护的构造函数和析构函数,不能更改它。 在Python 2.7中,我需要从EnviistListNER类派生,并将指针发送回C++代码。 在编译过程中,我遇到了这样的错误:
^{pr2}$
第一眼就知道你有问题。
py::class_<Event, ...>
只知道绑定到Event
,它有受保护的析构函数。在您必须将
Event
包装在一个公开析构函数的类中。在如果这不可能(因为你不能改变
EventBegin
,EventEnd
等的定义),那么你就必须编写一个多态容器,通过它自己的内部接口保存派生类,在内部将事件作为非多态对象处理。在这并不像听起来那么困难:
^{pr2}$当暴露一个函数时,Boost.Python将为每个参数生成转换器。对于类型为}的参数,生成的Python转换器将保存对象的副本,因此需要访问复制构造函数和析构函数。这种行为的基本原理是防止意外地暴露悬空引用。当将C++参数传递给Python时,情况也是如此。在
T
和{这种行为在以下情况下会出现问题:
EventListener::on_event(const Event&)
,如Boost.Python正在尝试创建一个将保存Event
副本的对象。要解决此问题,请考虑公开一个接受Event*
的辅助函数,然后委托给原始函数。在Event
对象传递给EventListenerWrap::on_event
中的Python。要解决此问题,请考虑将参数包装在boost::ref()
或boost::python::ptr()
中。在请注意,如果不创建副本,则会为悬空引用创建机会。如果实际的{{4CD> }对象由Python拥有,则其生命期至少需要与C++中的任何引用相同。同样的。如果实际的^ {< CD4}}对象是C++所拥有的,那么它的生存期至少需要在Python中引用它的时间长。在
一个有趣的细节是,
boost::python::pure_virtual()
将复制它包装的函数的签名,但它永远不会实际调用包装的函数。因此,被包装的函数可以有一个no-op/empty实现,但是如果pure_virtual
指示符被删除或者辅助函数被直接调用,那么提供一个实现是一个好主意。在另外,请注意,为了允许Python类从Boost.Python同学们Boost.Python必须公开
__init__()
方法。不提供任何方法,例如使用boost::python::no_init()
,将导致运行时错误。在下面是一个基于原始代码的最小完整示例,demonstrates公开了一个具有受保护的构造函数和析构函数的类、两个派生类以及通过Boost.Python公司名称:
^{pr2}$交互式使用:
当Python直接知道方法时,它将调用它而不经过Python。推进. 注意^ { < CD16> }没有通过C++发送,并且^ {CD17}}对象保持其^ {CD18}}类型。另一方面,当强制调度进入C++时,不会发生上报。当通过}。在
example.do_on_event()
调用Listener.on_event()
时,event
对象的类型是example.Event
,而不是{相关问题 更多 >
编程相关推荐