NpyString API#

在 2.0 版本加入.

此API允许访问存储在NumPy StringDType数组中的UTF-8字符串数据.有关StringDType设计的更多深入细节,请参见 NEP-55.

示例#

加载字符串#

假设我们正在为 StringDType 编写一个 ufunc 实现.如果我们得到一个指向 StringDType 数组条目开始的 const char *buf 指针,以及一个指向数组描述符的 PyArray_Descr * 指针,可以这样访问底层字符串数据:

npy_string_allocator *allocator = NpyString_acquire_allocator(
        (PyArray_StringDTypeObject *)descr);

npy_static_string sdata = {0, NULL};
npy_packed_static_string *packed_string = (npy_packed_static_string *)buf;
int is_null = 0;

is_null = NpyString_load(allocator, packed_string, &sdata);

if (is_null == -1) {
    // failed to load string, set error
    return -1;
}
else if (is_null) {
    // handle missing string
    // sdata->buf is NULL
    // sdata->size is 0
}
else {
    // sdata->buf is a pointer to the beginning of a string
    // sdata->size is the size of the string
}
NpyString_release_allocator(allocator);

打包一个字符串#

这个例子展示了如何将一个新的字符串条目打包到一个数组中:

char *str = "Hello world";
size_t size = 11;
npy_packed_static_string *packed_string = (npy_packed_static_string *)buf;

npy_string_allocator *allocator = NpyString_acquire_allocator(
        (PyArray_StringDTypeObject *)descr);

// copy contents of str into packed_string
if (NpyString_pack(allocator, packed_string, str, size) == -1) {
    // string packing failed, set error
    return -1;
}

// packed_string contains a copy of "Hello world"

NpyString_release_allocator(allocator);

类型#

type npy_packed_static_string#

一个表示”压缩”编码字符串的不透明结构体.数组缓冲区中的各个条目都是此结构体的实例.对结构体中数据的直接访问是未定义的,库的未来版本可能会更改字符串的压缩表示.

type npy_static_string#

一个未解包的字符串,允许访问 UTF-8 字符串数据.

typedef struct npy_unpacked_static_string {
    size_t size;
    const char *buf;
} npy_static_string;
size_t size#

字符串的大小,以字节为单位.

const char *buf#

字符串缓冲区.保存 UTF-8 编码的字节.目前不以空字符串结尾,但我们可能会决定在未来添加空终止符,因此不要依赖于是否存在空终止符.

注意这是一个 const 缓冲区.如果你想修改数组中的一个条目,你应该创建一个新的字符串并将其打包到数组条目中.

type npy_string_allocator#

一个指向处理字符串分配对象的不透明指针.在使用分配器之前,你必须获取分配器锁,并在完成与分配器管理的字符串交互后释放锁.

type PyArray_StringDTypeObject#

在Python中支持StringDType实例的C结构体.属性存储了对象创建时的设置,一个管理与DType实例相关联数组的字符串分配的``npy_string_allocator``实例,以及几个缓存关于在cast和ufunc循环实现中常用到的缺失字符串对象信息的属性.

typedef struct {
    PyArray_Descr base;
    PyObject *na_object;
    char coerce;
    char has_nan_na;
    char has_string_na;
    char array_owned;
    npy_static_string default_string;
    npy_static_string na_name;
    npy_string_allocator *allocator;
} PyArray_StringDTypeObject;
PyArray_Descr base#

基础对象.使用此成员访问所有描述符对象共有的字段.

PyObject *na_object#

表示空值的对象的引用.如果没有空值(默认情况下),这将是 NULL.

char coerce#

1 如果启用了字符串强制转换,否则为 0.

char has_nan_na#

1 如果缺失的字符串对象(如果有)类似于 NaN,否则为 0.

char has_string_na#

1 如果缺失的字符串对象(如果有)是一个字符串,否则为 0.

char array_owned#

1 如果数组拥有 StringDType 实例,否则为 0.

npy_static_string default_string#

操作中使用的默认字符串.如果缺失的字符串对象是一个字符串,这将包含缺失字符串的字符串数据.

npy_static_string na_name#

如果存在,则缺少的字符串对象的名称.否则为空字符串.

npy_string_allocator allocator#

与拥有此描述符实例的数组相关联的分配器实例.只有在获取了allocator_lock之后才能直接访问分配器,并且在不再需要分配器后应立即释放锁.

函数#

npy_string_allocator *NpyString_acquire_allocator(const PyArray_StringDTypeObject *descr)#

获取附加到 descr 的分配器的互斥锁.必须在此函数返回的分配器上调用 NpyString_release_allocator 一次.请注意,在持有分配器互斥锁时不应该调用需要 GIL 的函数,因为这可能会导致死锁.

void NpyString_acquire_allocators(size_t n_descriptors, PyArray_Descr *const descrs[], npy_string_allocator *allocators[])#

同时获取锁定多个描述符所附分配器的互斥锁.对于数组中的每个 StringDType 描述符,在分配器数组中写入一个指向相关分配器的指针.如果任何描述符不是 StringDType 实例,则在该条目的分配器数组中写入 NULL.

n_descriptors 是要检查的 descrs 数组中的描述符数量.任何在 n_descriptors 元素之后的描述符都会被忽略.如果 descrs 数组不包含 n_descriptors 元素,将会发生缓冲区溢出.

如果传递了指向同一描述符的多个指针,只会获取一次分配器互斥锁,但会适当地设置相同的分配器指针.在此函数返回后必须释放分配器互斥锁,参见 NpyString_release_allocators.

注意,需要 GIL 的函数不应在持有分配器互斥锁时调用,因为这可能会导致死锁.

void NpyString_release_allocator(npy_string_allocator *allocator)#

释放一个分配器的互斥锁.这必须在获取分配器互斥锁并且所有需要分配器的操作完成后精确调用一次.

如果你需要释放多个分配器,请参见 NpyString_release_allocators,它可以正确处理在给定对同一分配器的多个引用时只释放一次分配器.

void NpyString_release_allocators(size_t length, npy_string_allocator *allocators[])#

释放锁定 N 个分配器的互斥锁.``length`` 是分配器数组的长度.NULL 条目将被忽略.

如果多次传递指向同一分配器的指针,则仅释放一次分配器互斥锁.

int NpyString_load(npy_string_allocator *allocator, const npy_packed_static_string *packed_string, npy_static_string *unpacked_string)#

packed_string 的压缩内容提取到 unpacked_string 中.

unpacked_stringpacked_string 数据的只读视图,不应使用它来修改字符串数据.如果 packed_string 是空字符串,则将 unpacked_string.buf 设置为 NULL 指针.如果解包字符串失败,则返回 -1;如果 packed_string 是空字符串,则返回 1;否则返回 0.

一个有用的模式是定义一个栈分配的 npy_static_string 实例,初始化为 {0, NULL},并将指向栈分配的未打包字符串的指针传递给这个函数.这个函数可以用来同时解包一个字符串并确定它是否为空字符串.

int NpyString_pack_null(npy_string_allocator *allocator, npy_packed_static_string *packed_string)#

将空字符串打包到 packed_string 中.成功时返回 0,失败时返回 -1.

int NpyString_pack(npy_string_allocator *allocator, npy_packed_static_string *packed_string, const char *buf, size_t size)#

将缓冲区 buf 指向的前 size 个条目复制并打包到 packed_string 中.成功时返回 0,失败时返回 -1.