如何使用Boost.Python从C ++对象创建Python对象

时间:2012-07-03 10:13:21

标签: c++ inheritance python-2.7 boost-python

我有一个使用很多类的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

我得到了这个输出:

  

&lt; sso.View对象位于0x7f9d2681a4b0&gt;

但是我的C ++调试器告诉我变量'v'(python'myview')是一个'sso::Object'实例,而不是'sso::View'实例。调用sso::View::View()但变量类型不是视图,我不知道为什么。你对此有什么想法吗?你做过类似的事情并找到了一种方法让它发挥作用吗?

我使用Python2.7和Boost.Python1.49以及gcc版本4.6.1

编辑:我犯了一个错误:sso::Drawable不是从sso::Object继承,而是sso::View做的(=多重继承)。

1 个答案:

答案 0 :(得分:1)

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>(当然你也必须通过{{{}创建它。 1}}

除此之外,我发现您发布的代码没有任何问题。 sso.BlahDeBlah()是否继承自sso::View?如果是这种情况,并且您已经见证了sso::Object被调用,那么我认为当它告诉您对象类型为sso::view::View()时,您可能只是误解了调试器。也许它在你正在调试的时候有一个指向基类或类似东西的指针?

从python中调用sso::Objectmyview.insert时会发生什么?

编辑:我怀疑(虽然我可能错了)您可能没有在编译器中启用RTTI,因此myview.remove只是返回实现您在调用{{1时所使用的函数的类型}}。这肯定会解释为什么你在typeid()时得到typeid()但在其他函数中得到不同答案。

无论如何,我一直在仔细研究文档,我认为你的问题实际上是你提供了覆盖sso::View方法的能力,但你实际上没有用任何方法覆盖它

如果你看一下insert boost :: python函数at the bottom of this file的解除,你会看到一条评论:

raw_draw

所以你所看到的只是预期的行为。如果为pure_virtual中的// // 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. // 或继承自它的python类提供覆盖,则不应再出现此错误。