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

时间:2015-07-29 13:16:08

标签: python cython

这可能是一个愚蠢的问题,但是如何将“原始”指针传递给Cython对象的构造函数?问题似乎是__init____cinit__不能是cdefcpdef,但必须是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

1 个答案:

答案 0 :(得分:3)

根据使用情况,有许多选项。我认为假设你能够从Python构建你的类(指针没有意义)因此限制。

在你的例子中(我怀疑是简化的)你可以把malloc调用放在构造函数中:

# rest of class definition goes here
def __init__(self,size):
  self.ptr = malloc(size)
# and more code follows

另一种可能性是使用静态方法而不是__init__。 (为此目的,这在Cython文档中实际建议:http://docs.cython.org/src/userguide/extension_types.html#c-methods)。我刚从文档中复制了这个例子:

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代码处理它们将是有用的。一个好的大纲是http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html#create-cython-wrapper-class - 根据你想做的事情,你可能只选择创建一个构造函数和析构函数,而不是映射成员函数(如果有的话)。