C++ 类 和 Python 对象
C++ Classes and Python Objects
我有两个抽象的 C++ classes,我在 python 中公开和派生它们。我试图在 C++ 中提取那些派生对象并调用其中一个 classes 的某些方法,将另一个 class 的实例传递给第一个。 classes 定义如下:
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 class 只是用随机数填充数字数组,然后 B::b
打印这些数字以进行调试。
我可以毫无问题地导入它们并将两个 class 提取到 boost::shared_ptr
。甚至会调用其初始化程序中的任何 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
的派生?
问题是必须将摘要 classes 声明为 boost::noncopyable
。正如 documentation 所述:
boost::noncopyable
[sic] Suppresses automatic registration of to_python conversions which copy T instances. Required when T has no publicly-accessible copy constructor.
所以我们可以将 python 对象转换为 C++ 实例,但不能反之亦然,当我们尝试这样做时会导致问题中的错误。
解决方案实际上在 this 问题答案的评论中。
在wrapper class中,通过引用而不是通过值传递对象;所以 class 不必转换为 python。这使得包装器看起来像这样:
struct B_wrapper : B, py::wrapper<B> {
void b(const A& a) {
this->get_override("b")(boost:ref(a));
}
};
我有两个抽象的 C++ classes,我在 python 中公开和派生它们。我试图在 C++ 中提取那些派生对象并调用其中一个 classes 的某些方法,将另一个 class 的实例传递给第一个。 classes 定义如下:
struct A {
std::vector<int> numbers;
virtual void a() = 0;
};
struct B {
virtual void b(const A& a) = 0;
};
我使用 boost::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 class 只是用随机数填充数字数组,然后 B::b
打印这些数字以进行调试。
我可以毫无问题地导入它们并将两个 class 提取到 boost::shared_ptr
。甚至会调用其初始化程序中的任何 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
的派生?
问题是必须将摘要 classes 声明为 boost::noncopyable
。正如 documentation 所述:
boost::noncopyable
[sic] Suppresses automatic registration of to_python conversions which copy T instances. Required when T has no publicly-accessible copy constructor.
所以我们可以将 python 对象转换为 C++ 实例,但不能反之亦然,当我们尝试这样做时会导致问题中的错误。
解决方案实际上在 this 问题答案的评论中。
在wrapper class中,通过引用而不是通过值传递对象;所以 class 不必转换为 python。这使得包装器看起来像这样:
struct B_wrapper : B, py::wrapper<B> {
void b(const A& a) {
this->get_override("b")(boost:ref(a));
}
};