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

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

我有一个使用大量类的 C++ 项目。主要的是'sso::Object'(每个类都在'sso'命名空间中)并且这个类被派生到一些其他类但是一个是抽象的:'sso::可绘制'。

这个类有两个纯虚方法 '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 object at 0x7f9d2681a4b0>

但是我的 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 确实(=多重继承)。

最佳答案

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

正如您告诉 boost python 将对象公开为 sso.View那么这就是 python 将其视为的内容。如果您要更改代码以公开 std::string作为sso.View那么 python 仍然会报告 <sso.View object at 0x7f9d2681a4b0>在你创建它之后。

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

除此之外,我看不出您发布的代码有任何问题。是否sso::View继承自 sso::Object ?如果是这样,并且您已经目睹了sso::view::View()被调用,那么我认为当调试器告诉您对象类型为 sso::Object 时,您可能只是误解了调试器。 .也许在您调试时它有指向基类或类似内容的指针?

当您调用 myview.insert 时会发生什么或 myview.remove来自 python?

编辑:我怀疑(虽然我可能是错的)你可能没有在你的编译器中打开 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 提供覆盖在 sso::View或者从它继承的 python 类,那么你应该不会再得到这个错误。

关于c++ - 如何使用 Boost.Python 从 C++ 对象创建 Python 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11308747/

相关文章:

c# - 如何摆脱虚拟表?密封类

c++ - 通过从文本文件中读取它的名称来构造一个对象

python - python threading.Lock() 是否锁定所有需要锁定的东西?

c++ - 如何获得专用模板以使用成员函数的非专用版本?

c++ - 从 C++11 中的 STL 容器继承

python - 为什么我不能像这样实现继承?

python - 异常处理中的这种奇怪行为是什么?

c++ - 如何访问 wchar_t* 的 wchar_t?

c++ - 通过发音查找相似词 - 算法、方法、库

c++ - Cpp Friend 函数无法访问私有(private)静态成员