使用Cython包装自定义类型C ++指针的最佳方法是什么?
例如:
import numpy as np
cimport numpy as np
cdef extern from "A_c.h"
cdef cppclass A:
A();
void Foo(A* vec);
cdef class pyA:
cdef A *thisptr
def ___cinit___(self):
self.thisptr = new A()
def __dealloc___(self):
del self.thisptr
我应该如何使用cython来包装Foo?我已经尝试了以下但是我从Buffer.py得到了断言错误或者A不是memoryview slice的基本类型的错误
def Foo(self, np.ndarray[A, mode='c'] vec)
def Foo(self, A[::1] vec)
答案 0 :(得分:2)
基本上每次要传递类型为A
的对象或指向它的指针时,都应该使用类型为pyA
的Python对象 - 这实际上非常类似于指向事实的指针它有引用计数,所以它就像C ++ 11中的shared_ptr,只是它只知道Python(或Cython)中的引用。 [编辑]请注意,Python对象可以是None
,您可以使用not None
子句轻松阻止它。
当然,这不仅适用于参数,也适用于返回类型,因此返回指向A
类型的对象的指针的每个方法都应返回pyA
- 对象。为此,您可以为示例cdef
创建一个setThis
方法名称,以允许设置包含的指针。
如上所述,如果以这种方式包装指针,内存管理是在Python中完成的,所以一方面你需要确保如果你的C ++对象拥有一个指向一个对象的指针,那么Python对象就不会被删除(例如,在Cython中存储对Python对象的引用)另一方面,如果它们仍然包含在Python对象中,则不应该从C ++中删除对象。如果在C ++中已经有某种内存管理,那么如果要删除C ++对象,你也可以为你的Cython对象添加标志。
为了说明如何在Cython中实现这一点,我稍微扩展了您的示例:
cdef extern from "A_c.h":
cdef cppclass A:
A()
void Foo(A* vec)
A* Bar()
cdef cppclass AContainer:
AContainer(A* element)
cdef class pyA:
cdef A *thisptr
def ___cinit___(self):
self.thisptr = new A()
def __dealloc___(self):
del self.thisptr
cdef setThis(self, A* other):
del self.thisptr
self.thisptr = other
return self
def Foo(self, pyA vec not None): # Prevent passing None
self.thisptr.Foo(vec.thisptr)
def Bar(self):
return pyA().setThis(self.thisptr.Bar())
cdef class pyAContainer:
cdef AContainer *thisptr
cdef pyA element
def __cinit__(self, pyA element not None):
self.element = element # store reference in order to prevent deletion
self.thisptr = new AContainer(element.thisptr)
def __dealloc__(self):
del self.thisptr # this should not delete the element
# reference counting for the element is done automatically