c++类和Python对象

C++ Classes and Python Objects

本文关键字:对象 Python 类和 c++      更新时间:2023-10-16

我有两个抽象的c++类,我在python中公开和派生它们。我试图在c++中提取这些派生对象,并调用其中一个类的一些方法,将另一个类的实例传递给第一个。这些类是这样定义的:

struct A {
    std::vector<int> numbers;
    virtual void a() = 0;
};
struct B {
    virtual void b(const A& a) = 0;
};

我使用boost::python

将它们暴露给Python
namespace py = boost::python;
struct A_wrapper : A, py:wrapper<A> {
    void a() {
        this->getoverride("a")();
    }
};
struct B_wrapper : B, py::wrapper<B> {
    void b(const A& a) {
        this->get_override("b")(a);
    }
};
BOOST_PYTHON_MODULE(example) {
    typedef std::vector<int> int_vec_t;
    py::class_<int_vec_t>("IntList")
        .def(py::vector_indexing_suite<int_vec_t>());
    py::class_<A_wrapper, boost::noncopyable>("A")
        .def_readwrite("numbers", &A::numbers)
        .def("a", py::pure_virtual(&A::a));
    py::class_<B_wrapper, boost::noncopyable>("B")
        .def("b", py::pure_virtual(&B::b));
}

我的python类只是用随机数填充数字数组,B::b打印这些数字用于调试。

我可以导入它们并将这两个类提取到boost::shared_ptr s中,没有问题。它们的初始化器中的任何python代码都被调用。

auto pyA = py::extract<boost::shared_ptr<A> >(/*py object containing derivation of A*/)();
auto pyB = py::extract<boost::shared_ptr<B> >(/*py object containing derivation of B*/)();

但当我尝试调用pyB->b(*pyA)时,我得到以下错误:

TypeError: No to_python (by-value) converter found for C++ type: A

我做错了什么?如何使用A的实例调用Python的B::b的派生?

问题是必须将抽象类声明为boost::noncopyable。如文档所述:

boost::noncopyable [sic]禁止复制T实例的to_python转换的自动注册。当T没有可公开访问的复制构造函数时需要。

因此,我们可以将python对象转换为c++实例,但不能将python对象转换为c++实例,这将导致当我们试图这样做时问题中的错误。

答案实际上就在这个问题答案的注释中。

包装器类中,通过引用而不是通过值传递对象;因此,该类不必转换为python。这使得包装器看起来像这样:

struct B_wrapper : B, py::wrapper<B> {
    void b(const A& a) {
        this->get_override("b")(boost:ref(a));
    }
};