在 Cython 中将指针传递给构造函数
Passing pointer to constructor in Cython
这可能是一个愚蠢的问题,但我如何将 "raw" 指针传递给 Cython 对象的构造函数?问题似乎是 __init__
和 __cinit__
不能是 cdef
或 cpdef
但必须是 def
.
这里的最佳实践解决方法是什么?为分配的内存创建包装器 class?
以下作品
# 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
有很多选项,具体取决于用例。 __init__
/__cinit__
旨在从 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++ 数据类型,这可能是最合适的,您可以从另一个函数获得或自己轻松构造,并且能够从 pure 中处理这些数据类型将很有用Python 代码。 http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html#create-cython-wrapper-class 有一个很好的大纲——根据你想做什么,你可能只选择创建一个构造函数和析构函数,而不是映射成员函数(如果有的话)。
这可能是一个愚蠢的问题,但我如何将 "raw" 指针传递给 Cython 对象的构造函数?问题似乎是 __init__
和 __cinit__
不能是 cdef
或 cpdef
但必须是 def
.
这里的最佳实践解决方法是什么?为分配的内存创建包装器 class?
以下作品
# 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
有很多选项,具体取决于用例。 __init__
/__cinit__
旨在从 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++ 数据类型,这可能是最合适的,您可以从另一个函数获得或自己轻松构造,并且能够从 pure 中处理这些数据类型将很有用Python 代码。 http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html#create-cython-wrapper-class 有一个很好的大纲——根据你想做什么,你可能只选择创建一个构造函数和析构函数,而不是映射成员函数(如果有的话)。