【问题标题】:Cast a C++ abstract class from a Python object derived from that C++ abstract class从派生自 C++ 抽象类的 Python 对象转换 C++ 抽象类
【发布时间】:2020-09-01 03:39:01
【问题描述】:

我一直在尝试在 C++ 程序中转换一个抽象类,尝试与此网页和官方文档不同的解决方案,例如 this this,但没有任何效果。 我的 C++ 抽象类是:

class Base
{
    public:
    virtual ~Base(){};
    virtual void foo(){};
};

我要导入 python 的包装是:

class BasePy: public Base 
{
public:
    void foo() override
    {
        PYBIND11_OVERLOAD_PURE(
                void, 
                Base, 
                foo);
    }
};

我的导入函数和我的导入:

void import_base(pybind11::module m)
{
    using namespace pybind11;
    class_<Base, BasePy>(m, "Base")
        .def("foo", &Base::foo);
}
PYBIND11_MODULE(baselib, m)
{
    import_component(m);
}

我写了一个python类(derived.py):

import baselib

class test(baselib.Base):
    def __init__(self):
        self.x = 10;

    def foo(self):
        print(self.x)

最后是我的主要内容:

scoped_interpreter guard{};
auto obj = module::import("derived").attr("test")(); 
// obj = {<pybind11::handle> = 
//         {<pybind11::detail::object_api<pybind11::handle>> = 
//           {<pybind11::detail::pyobject_tag> = 
//             {<No data fields>}, <No data fields>
//           }, 
//           m_ptr = 0x7ffff706f1d0 
//         }, 
//         <No data fields>}
Base* bas = isinstance<Base>(obj) ? (Base*)obj.cast<void*>() : nullptr;
// bas = (Base*) 0x0

"baselib.so" 和可执行文件编译为 "derived.py" 在 python3 解释器上完美运行。 在解释器中:

derived.test.__base__ : <class 'baselib.base'>
derived.test.__class__ : <class 'pybind11_builtins.pybind11_type'>
derived.baselib == baselib : true
baselib.base.__base__ : <class 'pybind11_builtins.pybind11_object'>
baselib.base.__class__ : <class 'pybind11_builtins.pybind11_type'>

我不明白什么?

【问题讨论】:

    标签: python c++ pybind11


    【解决方案1】:

    尤里卡! 找到解决办法,导入类的时候没有添加蹦床类的init函数:

    void import_base(pybind11::module m)
    {
        using namespace pybind11;
        class_<Base,/*Holder*/ BasePy>(m, "Base")
        // You can add a holder like std::shared_ptr<Base> in "Holder"
            .def(init<>())// <--- THIS
            .def("foo", &Base::foo);
    }
    

    而在python类中,我们需要像这样添加“抽象类初始化器”(它是蹦床初始化器):

    class test(baselib.Base):
        def __init__(self):
            baselib.Base.__init__(self) // Adding this line
            self.x = 10;
    

    还有……瞧!问题解决了。

    【讨论】:

      猜你喜欢
      • 2011-02-01
      • 1970-01-01
      • 2013-11-30
      • 1970-01-01
      • 1970-01-01
      • 2012-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多