Woo*_*193 9 c python pointers cython python-extensions
我正在编写代码来将(可能)非常大的整数值存储到chars由指针引用的数组中.我的代码看起来像这样:
cdef class Variable:
cdef unsigned int Length
cdef char * Array
def __cinit__(self, var, length):
self.Length = length
self.Array = <char *>malloc(self.Length * sizeof(char)) # Error
for i in range(self.Length):
self.Array[i] = <char>(var >> (8 * i))
def __dealloc__(self):
self.Array = NULL
Run Code Online (Sandbox Code Playgroud)
当我尝试编译代码时,我在注释行中收到错误"存储临时Python引用的不安全C派生".我的问题是:我在C中存储的临时Python参考和存储,以及如何修复它?
问题是在引擎盖下创建了一个临时变量来在分配之前保存数组,self.Array并且一旦该方法退出就不会有效.
请注意,文档建议:
用于在Python堆上分配内存的C-API函数通常比上面的低级C函数更受欢迎,因为它们提供的内存实际上是在Python的内部内存管理系统中考虑的.它们还对较小的内存块进行了特殊优化,通过避免代价高昂的操作系统调用来加速其分配.
因此,您可以编写如下,似乎按预期处理此用例:
from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free
cdef class Variable:
cdef unsigned int Length
cdef char * Array
def __cinit__(self, var,size_t length):
self.Length = length
self.Array = <char *>PyMem_Malloc(length * sizeof(char))
#as in docs, a good practice
if not self.Array:
raise MemoryError()
for i in range(self.Length):
self.Array[i] = <char>(var >> (8 * i))
def __dealloc__(self):
PyMem_Free(self.Array)
Run Code Online (Sandbox Code Playgroud)
@ rll的答案在清理代码和"正确完成所有事情"方面做得非常好(最重要的是__dealloc__在问题中缺少的内存释放!).
导致错误的实际问题是您没有cimport编辑malloc.因为这个Cython假设它malloc是一个Python函数,返回一个你想要转换为的对象char*.在文件的顶部,添加
from libc.stdlib cimport malloc, free
Run Code Online (Sandbox Code Playgroud)
它会工作的.或者PyMem_Malloc像@rll一样使用(cimporting),这样也可以.