Cython从函数

时间:2018-02-26 19:12:12

标签: python cython

我是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实际上存储在一个临时变量中,该变量在函数末尾被释放。

非常感谢任何帮助。

1 个答案:

答案 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()。我不认为这些变化中的任何一个都与您的错误直接相关。