cython:ndarray字符串的内存视图(或直接ndarray索引)

ARF*_*ARF 5 python numpy cython

如何指定包含字符串的ndarray的内存视图?

char[:],, char*[:]...不行.

为了说明,我的问题是函数的定义abc(...):

cdef void abc(char[:] in_buffer):
    cdef char * element
    element = address(in_buffer[1])
    ...

def main():
    cdef Py_ssize_t i, n = 100

    a = np.array(['ABC', 'D', 'EFGHI'])
    for i in range(n):
        abc(a)
Run Code Online (Sandbox Code Playgroud)

如果无法访问内存视图,我可以自己实现直接阵列访问吗?我需要避免GIL的功能abc(...).


编辑1:回应Bi Rico的回答.

我的目标是为函数释放GIL,abc(...)并在其中处理ndarray in_buffer带有c字符串函数的字符串元素.即,如下所示:

cdef void abc(char[:, ::1] in_buffer) nogil:
    cdef int max_elt_length = in_buffer.shape[1]+1
    cdef char element[max_elt_length+1]
    cdef int length

    for i in range(in_buffer.shape[0]+1):  # is this equivalent to in_buffer.dtype.itemsize + 1 ?
       element[max_elt_length] = 0   # add null-terminator for full-size elements
       memcpy(element, address(buffer[i, 0]), max_length)
       length = strlen(element)
       ...
Run Code Online (Sandbox Code Playgroud)

Bi *_*ico 6

问题是numpy数组dtypes必须具有固定的大小.当你创建一个"字符串"数组时,你实际上是在制作一个固定长度字符数组的数组.试试这个:

import numpy as np

array = np.array(["cat", "in", "a", "hat"])
array[2] = "Seuss"
print(array)
# ['cat' 'in' 'Seu' 'hat']
print(array.dtype)
# dtype('|S3')
print(array.dtype.itemsize)
# 3
Run Code Online (Sandbox Code Playgroud)

考虑到这一点,你可以这样:

cdef void abc(char[:, ::1] in_buffer):
    cdef char * element
    element = address(in_buffer[1, 0])
Run Code Online (Sandbox Code Playgroud)

然后当你传递数组时,abc你需要做类似的事情:

a = np.array(['ABC', 'D', 'EFGHI'])
array_view = a.view('uint8').reshape(a.size, a.dtype.itemsize)
abc(array_view)
Run Code Online (Sandbox Code Playgroud)

这只是一种方法,但这是我推荐的方法而不了解更多关于你要做什么的方法.