使用 pybind11 包装 C++ 抽象类时出错

Posted

技术标签:

【中文标题】使用 pybind11 包装 C++ 抽象类时出错【英文标题】:Error by wrapping C++ abstract class with pybind11 【发布时间】:2020-07-11 21:32:38 【问题描述】:

我试图做一个简单的例子来用 pybind 包装一个抽象的 C++ 类。代码是:

#include <pybind11/pybind11.h>
#include <ostream>
#include <iostream>
namespace py = pybind11;
using namespace std;

class Base

public:
    virtual void test() = 0;

;
class Derived: public Base

public:
    void test() cout << "Test";
;


PYBIND11_MODULE(example,m) 
    py::class_<Base, Derived>(m, "Base")
        .def(py::init<>())
        .def("test", &Derived::test);

当我运行以下命令时

c++ -O3 -Wall -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` abstract_test.cpp -o example`python3-config --extension-suffix`\n

我得到错误:

In file included from abstrakt_test.cpp:1:
/home/anaconda3/envs/pybind/lib/python3.8/site-packages/pybind11/include/pybind11/pybind11.h: In instantiation of ‘Return (Derived::* pybind11::method_adaptor(Return (Class::*)(Args ...)))(Args ...) [with Derived = Base; Return = void; Class = Derived; Args = ]’:
/home/anaconda3/envs/pybind/lib/python3.8/site-packages/pybind11/include/pybind11/pybind11.h:1118:45:   required from ‘pybind11::class_<type_, options>& pybind11::class_<type_, options>::def(const char*, Func&&, const Extra& ...) [with Func = void (Derived::*)(); Extra = ; type_ = Base; options = Derived]’
abstrakt_test.cpp:23:36:   required from here
/home/anaconda3/envs/pybind/lib/python3.8/site-packages/pybind11/include/pybind11/pybind11.h:1032:19: error: static assertion failed: Cannot bind an inaccessible base class method; use a lambda definition instead
     static_assert(detail::is_accessible_base_of<Class, Derived>::value,
                   ^~~~~~
/home/anaconda3/envs/pybind/lib/python3.8/site-packages/pybind11/include/pybind11/pybind11.h:1034:12: error: cannot convert ‘void (Derived::*)()’ to ‘void (Base::*)()’ in return
     return pmf;
            ^~~

【问题讨论】:

DerivedBase 的子类时,您不能将Derived 用作class_ 调用中的父类。 【参考方案1】:

您还需要“包装”Base。否则,您将在导入时收到以下异常:

ImportError: generic_type: type "Derived" referenced unknown base type "Base"

另外,Derived 的包装顺序是错误的:

py::class_&lt;Derived, Base&gt;(m, "Derived")

完整示例:

PYBIND11_MODULE(example,m) 
    py::class_<Base>(m, "Base");

    py::class_<Derived, Base>(m, "Derived")
            .def(py::init<>())
            .def("test", &Derived::test);

【讨论】:

以上是关于使用 pybind11 包装 C++ 抽象类时出错的主要内容,如果未能解决你的问题,请参考以下文章

使用 Pybind11 包装 STL 容器返回类型

_IO_FILE 的 Pybind11 文件指针包装器

基于pybind11为C++提供Python接口

使用pybind11开发python扩展库

尝试在 Python 3 中使用 C++ 类时出错

Pybind11 默认参数 numpy 数组或无