我是Cython的新手,所以这可能相当微不足道,但我无法在任何地方找到答案。
我已经定义了一个结构类型,我想编写一个函数来正确初始化所有字段并返回指向新结构的指针。
from cpython.mem import PyMem_Malloc
ctypedef struct cell_t:
DTYPE_t[2] min_bounds
DTYPE_t[2] max_bounds
DTYPE_t size
bint is_leaf
cell_t * children[4]
DTYPE_t[2] center_of_mass
UINT32_t count
cdef cell_t * make_cell(DTYPE_t[2] min_bounds, DTYPE_t[2] max_bounds):
cdef cell_t * cell = <cell_t *>PyMem_Malloc(sizeof(cell_t)) # <- Fails here
if not cell:
MemoryError()
cell.min_bounds[:] = min_bounds
cell.max_bounds[:] = max_bounds
cell.size = min_bounds[0] - max_bounds[0]
cell.is_leaf = True
cell.center_of_mass[:] = [0, 0]
cell.count = 0
return cell
但是,当我尝试编译它时,我在编译期间遇到以下两个错误:
cdef cell_t * make_cell(DTYPE_t[2] min_bounds, DTYPE_t[2] max_bounds):
cdef cell_t * cell = <cell_t *>PyMem_Malloc(sizeof(cell_t))
^
Casting temporary Python object to non-numeric non-Python type
------------------------------------------------------------
cdef cell_t * make_cell(DTYPE_t[2] min_bounds, DTYPE_t[2] max_bounds):
cdef cell_t * cell = <cell_t *>PyMem_Malloc(sizeof(cell_t))
^
Storing unsafe C derivative of temporary Python reference
------------------------------------------------------------
现在,我已经看了一遍,从我可以收集到的内容,cell
实际上存储在一个临时变量中,该变量在函数末尾被释放。
非常感谢任何帮助。
答案 0 :(得分:4)
cell.min_bounds = min_bounds
这并不是你认为它做的事情(尽管我并不是100%确定它做了什么)。您需要逐个元素地复制数组:
cell.min_bounds[0] = min_bounds[0]
cell.min_bounds[1] = min_bounds[1]
max_bounds
相同。
我怀疑该行给出的错误信息是:
cell.center_of_mass = [0, 0]
这是试图将一个Python列表分配给一个C数组(记住数组和指针在C中有些可以互换),这没有多大意义。再次,你做
cell.center_of_mass[0] = 0
cell.center_of_mass[1] = 0
这一切与C行为基本一致,即没有运营商将整个数组相互复制,你需要逐个元素地复制。
修改强>
然而,这不是你眼前的问题。您尚未声明PyMem_Malloc
,因此它被假定为Python函数。你应该做
from cpython.mem cimport PyMem_Malloc
确保cimport
编辑,而不是import
编辑
<强> EDIT2:强>
以下编辑对我来说很好:
from cpython.mem cimport PyMem_Malloc
ctypedef double DTYPE_t
ctypedef struct cell_t:
DTYPE_t[2] min_bounds
DTYPE_t[2] max_bounds
cdef cell_t * make_cell(DTYPE_t[2] min_bounds, DTYPE_t[2] max_bounds) except NULL:
cdef cell_t * cell = <cell_t *>PyMem_Malloc(sizeof(cell_t))
if not cell:
raise MemoryError()
return cell
我已经减少cell_t
一点(只是为了避免必须声明UINT32_t
)。我还给cdef
函数except NULL
,以便在需要时发出错误信号并在raise
之前添加MemoryError()
。我不认为这些变化中的任何一个都与您的错误直接相关。