2

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

我得到这个输出:

<sso.View 对象位于 0x7f9d2681a4b0>

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

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

编辑:我犯了一个错误:sso::Drawable不继承自sso::Object,但sso::View确实(=多重继承)。

4

1 回答 1

1

python的输出<sso.View object at 0x7f9d2681a4b0>只是告诉你它认为对象类型被称为什么,它与在 C++ 级别创建的对象的实际类型无关。

正如您已经告诉 boost python 公开对象那样sso.View,这就是 python 所看到的。如果您要将代码更改为公开std::string,那么在您创建它之后, sso.Viewpython 仍会报告。<sso.View object at 0x7f9d2681a4b0>

同样,如果您"View"将 C++ 更改为,"BlahDeBlah"那么 python 会将对象报告为<sso.BlahDeBlah object at 0x7f9d2681a4b0>(当然您还必须通过sso.BlahDeBlah()

除此之外,我看不出您发布的代码有什么问题。sso::View继承sso::Object自? 如果是这种情况,并且您目睹了sso::view::View()被调用,那么我认为您可能只是在调试器告诉您对象是 type 时误解了它sso::Object。也许它有一个指向基类的指针或在您调试时类似的东西?

当您调用myview.insertmyview.remove从 python 调用时会发生什么?

编辑:我怀疑(尽管我可能是错的)你可能没有在你的编译器中打开 RTTI,所以typeid()只是返回实现你在调用时所在函数的类型typeid()。这肯定会解释为什么你sso::Viewinsert其他功能中得到不同的答案。

无论如何,我一直在研究文档,我认为您的问题实际上是您提供了覆盖该raw_draw方法的能力,但您实际上并没有用任何东西覆盖它。

如果您查看此文件底部pure_virtual的boost::python 函数的声明,您会看到一条注释:

//
// 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如果您为in或从它继承的 python 类提供覆盖,sso::View那么您不应再收到此错误。

于 2012-07-03T10:57:46.327 回答