在Cython中包装自定义类型C ++指针 [英] Wrapping custom type C++ pointer in Cython
问题描述
使用Cython包装自定义类型C ++指针的最佳方法是什么?
What is the best way to wrap a custom type C++ pointer using Cython?
例如:
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的基本类型的错误
How should I use cython to wrap Foo? I have tried the following but I have gotten assertion errors from Buffer.py or the error that A is not a base type of memoryview slice
def Foo(self, np.ndarray[A, mode='c'] vec)
def Foo(self, A[::1] vec)
推荐答案
基本上,每次您要传递A
类型的对象或指向它的指针时,都应使用pyA
类型的Python对象-除了具有引用计数这一事实外,它实际上与指针非常相似,因此它类似于在C ++ 11中使用shared_ptr ,只是它只知道Python(或Cython)中的引用. 请注意,Python对象可以是None
,您可以使用not None
子句轻松地防止这种情况.
Basically every time you want to pass an object of type A
or a pointer to it you should use a Python object of type pyA
- which is actually very similar to a pointer apart from the fact that it has reference counting, so it is like a shared_ptr in C++11, just that it only knows about references in Python (or Cython). Note that Python objects can be None
, you can easily prevent this using the not None
clause.
当然,这不仅适用于参数,而且适用于返回类型,因此,每个返回指向A
类型对象的指针的方法都应返回pyA
-object.为此,您可以创建一个cdef
方法名称,例如setThis
,它可以设置包含的指针.
Of course this is not only true for parameters but also for return types, so every method that returns a pointer to an object of type A
should return a pyA
-object instead. For doing this you can create a cdef
method name for example setThis
that allows to set the pointer that is contained.
如上所述,如果以这种方式包装指针,则内存管理是在Python中完成的,因此,一方面,您需要确保如果C ++对象持有指向该对象的指针,则该Python对象不会被删除(例如,通过在Cython中存储对Python对象的引用),另一方面,如果它们仍包含在Python对象中,则不应从C ++中删除它们.如果您已经删除了C ++对象,或者您已经在C ++中进行了某种内存管理,那么也可以在Cython对象中添加标志.
As mentioned already above, memory management is done in Python if you wrap pointers this way so on the one hand you need to ensure that if your C++ objects holds a pointer to an object that the Python object is not deleted (e.g. by storing a reference to the Python object in Cython) and on the other hand you should not delete objects from C++ if they are still contained in a Python object. You could also add flags to your Cython objects if the C++ object shall be deleted or not if you already have some kind of memory management in C++.
为了说明如何在Cython中实现这一点,我对示例进行了扩展:
I've extended your example a bit in order to illustrate how this can be implemented in 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
这篇关于在Cython中包装自定义类型C ++指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!