我有一个使用很多类的C++项目。主要的是“sso::Object
”(每个类都在“sso”命名空间中),并且该类派生到其他一些类中,但其中一个抽象:“sso::Drawable
”。
该类有两个纯虚拟方法'sso::Drawable::set_opacity
'和'sso::Drawable::raw_draw
',并且派生到实现这两个方法的其他类(例如'sso::View
')中。
当整个项目在C++中使用时,它运行良好,但是我也想在Python中使用它,因此我创建了一个Boost.Python模块,如下所示:
class DrawableWrapper : public sso::Drawable , public wrapper<sso::Drawable> {
public:
void set_opacity(byte opacity) { this->get_override("set_opacity")(opacity); }
void raw_draw(const sso::Rect &rect,sso::Target &target,const sso::Position &position) const {
this->get_override("raw_draw")(rect,target,position);
}
};
BOOST_PYTHON_MODULE(sso) {
class_<DrawableWrapper,boost::noncopyable> ("Drawable",init<>())
.add_property ("opacity",&sso::Drawable::get_opacity)
// python_sso_getter & python_sso_setter_* are only used for an easier access to accessors
.add_property ("position",python_sso_getter<sso::Drawable,sso::Position,&sso::Drawable::get_position>,python_sso_setter_1_const<sso::Drawable,sso::Position,&sso::Drawable::set_position>)
.def("raw_draw",pure_virtual(&sso::Drawable::raw_draw))
;
class_<sso::View,bases<sso::Drawable> > ("View",init<>())
.def("insert",python_sso_setter_1<sso::View,sso::Drawable*,&sso::View::insert>)
.def("remove",&sso::View::erase)
;
}
这段代码编译没有错误,但是当我在Python中执行这些行时:
myview = sso.View()
print myview
我得到以下输出:
但是我的C++调试器告诉我变量'v'(python'myview')是'
sso::Object
'实例,而不是'sso::View
'实例。 sso::View::View()
被调用,但是变量类型不是 View ,我也不知道为什么。您对此有什么想法吗?您是否做了类似的事情,并找到了使其工作的方法?我使用Python2.7和Boost.Python1.49和gcc版本4.6.1
编辑:我犯了一个错误:
sso::Drawable
不能从sso::Object
继承,但是sso::View
可以(=多重继承)。 最佳答案
python的输出<sso.View object at 0x7f9d2681a4b0>
只是python,告诉您它认为该对象类型被称为什么,它与在C++级别创建的实际对象类型无关。
正如您告诉boost python将对象公开为sso.View
一样,这就是python将其视为的对象。如果您要更改代码以将std::string
公开为sso.View
,则python创建后仍会报告<sso.View object at 0x7f9d2681a4b0>
。
同样,如果要将C++中的"View"
更改为"BlahDeBlah"
,则python会将对象报告为<sso.BlahDeBlah object at 0x7f9d2681a4b0>
(当然,您还必须通过sso.BlahDeBlah()
创建该对象
除此之外,我看不到您发布的代码有任何问题。 sso::View
是否继承自sso::Object
?如果是这种情况,并且您已经目睹了sso::view::View()
被调用,那么我认为当调试器告诉您对象的类型为sso::Object
时,您可能只是在误解调试器。也许在调试时它有一个指向基类的指针或类似的东西?
当您从python调用myview.insert
或myview.remove
时会发生什么?
编辑:我怀疑(尽管我可能错了)您可能未在编译器中打开RTTI,所以typeid()
仅返回实现调用typeid()
时所用功能的类型。这肯定可以解释为什么在sso::View
中得到insert
却在其他函数中得到不同的答案。
无论如何,我一直在仔细研究文档,我认为您的问题实际上是您提供了重写raw_draw
方法的能力,但实际上并未用任何方法替代它。
如果您看一下pure_virtual
boost::python函数at the bottom of this file的简化,您将看到一条注释:
//
// Passed a pointer to member function, generates a def_visitor which
// creates a method that only dispatches to Python if the function has
// been overridden, either in C++ or in Python, raising a "pure
// virtual called" exception otherwise.
//
因此,您所看到的只是预期的行为。如果您在
raw_draw
或从其继承的python类中提供sso::View
的替代,则您将不再遇到此错误。关于c++ - 如何使用Boost.Python从C++对象创建Python对象,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11308747/