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

10-10 10:39