在 cython 中返回 c++ 对象(最好不是指针)
Posted
技术标签:
【中文标题】在 cython 中返回 c++ 对象(最好不是指针)【英文标题】:Return c++ object (not a pointer preferably) in cython 【发布时间】:2016-09-02 06:24:37 【问题描述】:我有两个类(让我们假设最简单的类,实现并不重要)。我的defs.pxd
文件(带有 cython defs)如下所示:
cdef extern from "A.hpp":
cdef cppclass A:
A() except +
cdef extern from "B.hpp":
cdef cppclass B:
B() except +
A func ()
我的pyx
文件(带有python defs)如下所示:
from cython.operator cimport dereference as deref
from libcpp.memory cimport shared_ptr
cimport defs
cdef class A:
cdef shared_ptr[cquacker_defs.A] _this
@staticmethod
cdef inline A _from_this(shared_ptr[cquacker_defs.A] _this):
cdef A result = A.__new__(A)
result._this = _this
return result
def __init__(self):
self._this.reset(new cquacker_defs.A())
cdef class B:
cdef shared_ptr[cquacker_defs.B] _this
@staticmethod
cdef inline B _from_this(shared_ptr[cquacker_defs.B] _this):
cdef B result = B.__new__(B)
result._this = _this
return result
def __init__(self):
self._this.reset(new cquacker_defs.B())
def func(self):
return deref(self._this).func()
问题是我无法从 Python 返回非 Python 对象。实际上,我不想将我的 c++ 代码更改为返回指针而不是新对象(因为有很多这样的函数)。现在它给了我错误:
Cannot convert 'B' to Python object
如何从 python 中的另一个方法返回一个包含内部 c++ 对象的 python 对象?如果我只能在一些 c++ 更改之后才能做到这一点,我想要最优雅的解决方案,如果可能的话。
【问题讨论】:
不确定你在问什么,但我认为你不能将“原始”C++ 对象返回给 Python;必须有某种包装。一旦您可以在 Python 代码中访问该对象,您打算如何处理它? @BrenBarn 我更正了 B 定义中的一个错误,所以 B 的方法 func 返回了 A 对象。当然,我希望在 Python 中能够编写像a = b.func()
这样的东西,其中 b - 是 B 的包装器,a 是 A 的包装器。
您将需要使用复制或(更好的)移动构造函数来完成new A
。
@DavidW 你能告诉我如何更改我的代码吗?
【参考方案1】:
您的问题是您的包装类需要一个指针(指向 new
分配的对象),但您的函数在堆栈上返回一个 C++ 对象。要解决这个问题,您必须从堆栈中复制或移动对象。
首先确保您的 C++ 类 A
具有工作副本或移动构造函数。如果您的 c++ 类包含大型成员,则移动构造函数会更好。像这样包装这是 Cython:
cdef extern from "A.hpp":
cdef cppclass A:
A() except +
A(const A&) except +
# or A(A&&) except +
(不要将复制构造函数和移动构造函数都告诉 Cython - 它会混淆!C++ 无论如何都会在编译时找到正确的)。
然后,在func
中使用您的复制/移动构造函数和new
传递给您的python 包装器:
def func(self):
return A._from_this(new cquacker_defs.A(self._this.func()))
【讨论】:
但我不需要做 deref(self._ths) 吗? 我不这么认为。我相信 Cython 可以根据需要选择是否使用this.func
或 this->func
生成 c++ 代码。以上是关于在 cython 中返回 c++ 对象(最好不是指针)的主要内容,如果未能解决你的问题,请参考以下文章
Cython - 将 C++ 函数返回的 C++(向量和非向量)对象暴露给 Python
从 C++ 函数 Cython 返回包含 PyObject 的复杂对象
如何使用 Cython 向 Python 公开返回 C++ 对象的函数?