You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C语言中访问NumPy record(记录)的内容?

问题背景

假设我创建了如下代码:

import numpy as np

descriptor = np.dtype([
        ('left', np.double, 3),
        ('center', np.double, 3),
        ('right', np.double, 3),
    ])
value = np.zeros(10, dtype=descriptor)

可以验证value是由90个double类型数据组成的连续内存块。修改value[3]后,原数组也会同步变化,说明value[3]是指向该连续内存中某一位置的数据结构。

但value[3]究竟是什么?若将任意value[i]传入C函数,C代码该如何找到该元素对应的9个内存位置?对于普通非记录子数组,可使用PyArray_DATA宏获取数据位置,但尚未找到适用于NumPy Records的对应方法。

该元素的方法解析顺序(mro())如下:

[numpy.record, numpy.void, numpy.flexible, numpy.generic, object]

解答

1. value[i]的本质

value[i]是**numpy.record类型的标量对象**,它继承自numpy.void(属于NumPy的灵活类型numpy.flexible),本质是原数组对应位置内存的视图:

  • 它不独立分配内存,直接引用原数组连续内存块中对应单个record的起始位置
  • 单个numpy.record的大小等于定义的descriptor总字节数(此处为3*8 + 3*8 +3*8 = 72字节,对应9个double)
  • 修改该标量的字段(如value[i]['left'][0] = 1.0)会直接修改原数组的内存,因此原数组会同步变化

2. C语言中访问value[i]的内存位置

在NumPy C API中,numpy.record属于void类型的标量对象,可通过以下步骤获取其对应的内存指针:

步骤1:验证对象类型

首先确认传入的Python对象是numpy.void类型的标量:

#include <numpy/arrayobject.h>

// 假设传入参数为obj
if (!PyArrayScalar_Check(obj)) {
    PyErr_SetString(PyExc_TypeError, "Input must be a NumPy scalar");
    return NULL;
}

PyArray_Descr *descr = PyArrayScalar_DESCR(obj);
if (descr->type_num != NPY_VOID) {
    PyErr_SetString(PyExc_TypeError, "Input must be a NumPy void/record scalar");
    return NULL;
}

步骤2:获取内存起始地址

将对象转换为PyArrayScalarObject指针,直接访问其data成员,该成员即为对应record内存块的起始地址:

PyArrayScalarObject *scalar = (PyArrayScalarObject *)obj;
// 转换为double指针,匹配record的内部数据类型
double *record_data = (double *)scalar->data;

// 直接访问9个double:
// record_data[0]~record_data[2] → 'left'字段的3个值
// record_data[3]~record_data[5] → 'center'字段的3个值
// record_data[6]~record_data[8] → 'right'字段的3个值

补充:按字段名访问(可选)

如果需要按字段名精准访问,可通过descriptor获取字段的偏移量:

// 获取'left'字段的内存偏移量
npy_intp left_offset;
if (PyArrayDescr_GetFieldOffset(descr, "left", &left_offset) < 0) {
    return NULL;
}
double *left_data = (double *)((char *)scalar->data + left_offset);
// left_data[0], left_data[1], left_data[2] 即为'left'字段的三个值

内容的提问来源于stack exchange,提问作者Frank Yellin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 18:13:18