从从该抽象类派生的 Python 对象强制转换C++抽象类C++

Cast a C++ abstract class from a Python object derived from that C++ abstract class

本文关键字:抽象类 C++ 转换 Python 派生 对象      更新时间:2023-10-16

我一直在尝试在C++程序中转换一个抽象类,尝试与此网页和官方文档不同的解决方案,例如这个和这个,但没有任何效果。 我的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'>

我有什么不明白的?

尤里卡! 我找到了一个解决方案,当我导入类时,我没有添加蹦床类的 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;

和。。。瞧!问题解决了。