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

如何在C++中创建numpy表并实现跨C++与Python的双向访问

实现C++结构体与Python NumPy数组双向访问的方案

核心思路

要让C++结构体数组直接映射为Python的NumPy结构化数组,关键是保证内存布局完全一致,再通过pybind11完成类型绑定与数组创建。

步骤1:对齐C++结构体与NumPy dtype的内存布局

你的Python dtype已指定offsets,C++结构体需严格对应:

#include <cstdint>
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>

// 严格匹配NumPy dtype的内存布局
struct Table {
    float field1;  // 对应offsets[0] = 0,float32占4字节
    float field2;  // 对应offsets[4] = 4,紧跟field1之后
};

// 编译期验证结构体大小(可选但推荐,避免内存布局不一致)
static_assert(sizeof(Table) == 8, "Table struct size must match NumPy dtype size");

步骤2:C++侧创建可映射到NumPy的数组

用pybind11创建array_t<Table>,同时注入NumPy结构化类型信息,让Python能识别为结构化数组:

namespace py = pybind11;

py::array_t<Table> create_my_table(size_t length) {
    // 分配内存并初始化array_t对象
    auto arr = py::array_t<Table>(length);
    
    // 获取可写指针,C++侧直接操作数组元素
    auto ptr = arr.mutable_data();
    // 示例:初始化数据
    for (size_t i = 0; i < length; ++i) {
        ptr[i].field1 = 1.0f + static_cast<float>(i);
        ptr[i].field2 = 2.0f + static_cast<float>(i);
    }

    // 设置NumPy dtype元信息,让Python识别为结构化数组
    py::dict dtype_spec;
    dtype_spec["names"] = py::make_tuple("field1", "field2");
    dtype_spec["formats"] = py::make_tuple(py::dtype("float32"), py::dtype("float32"));
    dtype_spec["offsets"] = py::make_tuple(0, 4);
    dtype_spec["itemsize"] = sizeof(Table);

    arr.attr("dtype") = py::dtype(dtype_spec);

    return arr;
}

步骤3:绑定到Python模块

在pybind11的模块初始化函数中注册创建函数:

PYBIND11_MODULE(my_table_dll, m) {
    m.def("create_my_table", &create_my_table, py::arg("length"), "Create a structured NumPy array from C++ Table struct");
}

步骤4:Python侧验证与使用

编译DLL后,在Python中直接调用并操作:

import numpy as np
import my_table_dll

# 从C++创建表
table = my_table_dll.create_my_table(42)

# 验证是NumPy结构化数组
assert isinstance(table, np.ndarray)
assert table.dtype.names == ('field1', 'field2')
assert table.dtype['field1'] == np.float32

# 访问/修改数据(和原生NumPy数组用法完全一致)
print(table[0]['field1'])
table[1]['field2'] = 100.0

# C++侧通过array_t<Table>的指针也能读取到Python修改后的数据

关键注意事项

  • 内存对齐:如果结构体包含不同类型,可能需要用#pragma pack(push, 4)强制对齐,避免编译器默认对齐规则导致偏移错误。
  • 内存生命周期:array_t由pybind11自动管理,Python侧引用计数归零后会自动释放内存,无需手动处理。
  • 双向同步:C++和Python共享同一块内存,任意一侧修改数据,另一侧都会立刻看到最新值。

内容的提问来源于stack exchange,提问作者Max Yaffe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 19:06:06