返回python中的c++对象(最好不是指针)



我有两个类(让我们假设最简单的,实现并不重要)。我的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++进行一些修改之后才能做到这一点,我希望尽可能使用最优雅的解决方案。

你的问题是你的包装器类需要一个指针(一个new分配的对象),但你的函数返回堆栈上的c++对象。要解决这个问题,你必须从堆栈中复制或移动对象。

首先确保您的c++类A有一个工作的复制或移动构造函数。如果您的c++类包含大型成员,则使用move构造函数更好。像这样包装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()))

相关内容

  • 没有找到相关文章

最新更新