cython - 确定指针变量中的项数

时间:2017-06-08 14:52:45

标签: pointers cython

如何确定cython中指针变量中元素的数量?如果指针指向sizeof(ptr)/sizeof(int)变量,我在C中看到单向似乎是int。但这似乎不适用于cython。例如。当我试图将两个内存视图连接到一个指针时,如下所示:

from libc.stdlib cimport malloc, free
cdef int * join(int[:] a, int[:] b):

    cdef:
        int n_a = a.shape[0]
        int n_b = b.shape[0]
        int new_size =  n_a + n_b
        int *joined = <int *> malloc(new_size*sizeof(int))
        int i
    try:
        for i in range(n_a):
            joined[i] = a[i]

        for i in range(n_b):
            joined[n_a+i] = b[i]

        return joined
    finally:
        free(joined)

@cython.cdivision(True)
def join_memviews(int[:] n, int[:] m):

    cdef int[:] arr_fst = n
    cdef int[:] arr_snd = m
    cdef int *arr_new
    cdef int new_size

    arr_new = join(arr_fst,arr_snd)    
    new_size = sizeof(arr_new)/sizeof(int)

    return [arr_new[i] for i in range(new_size)]

从python脚本调用join_memviews时,我得不到所需的结果,例如:

# in python
a = np.array([1,2])
b = np.array([3,4])
a_b = join_memviews(a,b)

我也尝试使用类型

DTYPE = np.int
ctypedef np.int_t DTYPE_t

作为sizeof()内部的争论,但这也不起作用。

编辑:指针变量的处理显然对我来说有点粗心。我希望以下情况很好(即使这可能不是一种谨慎的做法):

cdef int * join(int[:] a, int[:] b, int new_size):

    cdef:
        int *joined = <int *> malloc(new_size*sizeof(int))
        int i

    for i in range(n_a):
        joined[i] = a[i]

    for i in range(n_b):
        joined[n_a+i] = b[i]

    return joined

def join_memviews(int[:] n, int[:] m):

    cdef int[:] arr_fst = n
    cdef int[:] arr_snd = m
    cdef int *arr_new
    cdef int new_size = n.shape[0] + m.shape[0]

    try: 
        arr_new = join(arr_fst,arr_snd, new_size)    

        return [arr_new[i] for i in range(new_size)]
    finally:
        free(arr_new)

1 个答案:

答案 0 :(得分:0)

你做不到。它在C中也不起作用。 sizeof(ptr)返回用于存储指针的内存量(通常为4或8,具体取决于您的系统),而不是数组的长度。您需要手动跟踪malloc ed数组的长度。

此外,以下代码是灾难的处方:

cdef int *joined = <int *> malloc(new_size*sizeof(int))
try:
   return joined
finally:
   free(joined)

free会在函数退出时立即发生,因此会向调用函数返回一个无效指针。

您应该使用正确管理的Python数组(来自numpy或标准库array模块),除非您绝对无法避免。