Python 在Cython中向构造函数传递指针

Python 在Cython中向构造函数传递指针,python,cython,Python,Cython,这可能是一个愚蠢的问题,但如何将“原始”指针传递给Cython对象的构造函数?问题似乎是\uuuu init\uuuu和\uuu cinit\uuuu不能是cdef或cpdef,但必须是def 这里的最佳做法是什么?是否为分配的内存创建包装器类 以下作品 # ex1.pyx from libc.stdlib cimport malloc, free cdef class Klass1: cdef void * ptr cdef void _init(self, void *

这可能是一个愚蠢的问题,但如何将“原始”指针传递给Cython对象的构造函数?问题似乎是
\uuuu init\uuuu
\uuu cinit\uuuu
不能是
cdef
cpdef
,但必须是
def

这里的最佳做法是什么?是否为分配的内存创建包装器类

以下作品

# ex1.pyx
from libc.stdlib cimport malloc, free

cdef class Klass1:
    cdef void * ptr

    cdef void _init(self, void * ptr):
        self.ptr = ptr

    def bar(self):
        free(self.ptr)

def foo():
    o = Klass1()
    o._init(malloc(100))
    o.bar()
但以下情况并非如此:

# ex2.pyx
from libc.stdlib cimport malloc, free

cdef class Klass2:
    cdef void * ptr

    def __init__(self, ptr):  # __init__ cannot be cdef
        self.ptr = ptr

    def bar(self):
        free(self.ptr)

def foo():
    o = Klass2(malloc(100))
    o.bar()
以下
setup.py
可用于构建:

from distutils.core import setup
from Cython.Build import cythonize

setup(name='ex1', ext_modules=cythonize('ex1.pyx')) # or ex2.pyx

根据用例的不同,有许多选项<代码>\uuuu init\uuuu/
\uuuu cinit\uuuu
设计用于从Python构造类(其中指针是无意义的),因此受到限制

在您的示例中(我怀疑简化了),您可以将
malloc
调用放在构造函数中:

# rest of class definition goes here
def __init__(self,size):
  self.ptr = malloc(size)
# and more code follows
另一种可能是使用静态方法,而不是
\uuuu init\uuuu
。(这实际上是Cython文档中为此目的建议的:)。我刚刚复制了文档中的示例:

cdef class OwnedPointer:
    cdef void* ptr

    cdef __dealloc__(self):
        if ptr != NULL:
            free(ptr)

    @staticmethod
    cdef create(void* ptr):
        p = OwnedPointer()
        p.ptr = ptr
        return ptr
第三种选择是按照您的建议使用包装器类——问题是您仍然必须以某种方式构造它们(因此您回到了前面提到的两种技术)。当指针实际指向已知的C/C++数据类型时,这可能是最合适的,您可以从另一个函数或自己轻松构造该数据类型,并且能够从纯Python代码处理这些数据类型将非常有用。一个好的大纲是在-取决于你想做什么,你可能只选择创建一个构造函数和析构函数,而不是映射成员函数(如果有的话)