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

Pybind11如何将N维numpy数组从Python传递到C++并适配std::vector

二维numpy数组传递到C++的正确实现

你之前的写法报错的核心原因是:numpy的多维数组是连续存储的单块内存,并非嵌套的数组结构,因此不能用py::array_t<py::array_t<float>>这种嵌套类型声明。

1. C++侧参数声明

直接使用带存储格式约束的py::array_t即可,示例如下:

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <vector>
#include <stdexcept>

namespace py = pybind11;

// 如果你用的是Python默认的float(对应numpy float64),把<float>替换成<double>即可
void modify_array(py::array_t<float, py::array::c_style | py::array::forcecast> input_arr) {
    // 逻辑实现见下文
}

参数中的py::array::c_style要求数组为行优先存储,py::array::forcecast会自动转换兼容的数值类型,避免格式报错。

2. 实现类似std::vector的读写效果

提供两种常用实现方式,可按需选择:

方式一:零拷贝直接操作(修改直接同步到Python侧原数组)

不需要额外内存拷贝,性能最高:

void modify_array(py::array_t<float, py::array::c_style | py::array::forcecast> input_arr) {
    py::buffer_info buf = input_arr.request();
    // 校验维度
    if (buf.ndim != 2) {
        throw std::runtime_error("输入必须为二维数组");
    }
    size_t rows = buf.shape[0];
    size_t cols = buf.shape[1];
    float* data_ptr = static_cast<float*>(buf.ptr);

    // 封装和vector[i][j]一致的访问接口
    auto arr = [&](size_t row, size_t col) -> float& {
        if (row >= rows || col >= cols) throw std::out_of_range("数组下标越界");
        return data_ptr[row * cols + col];
    };

    // 读写操作和vector完全一致
    float val = arr(0, 1); // 读取第0行第1列元素
    arr(1, 2) = 123.45f; // 修改第1行第2列元素,修改直接生效到Python侧数组
}

方式二:转成std::vector<std::vector>操作(兼容全部vector接口)

适合需要用到vector专属方法的场景,修改后可手动同步回原数组:

void modify_array(py::array_t<float, py::array::c_style | py::array::forcecast> input_arr) {
    py::buffer_info buf = input_arr.request();
    if (buf.ndim != 2) {
        throw std::runtime_error("输入必须为二维数组");
    }
    size_t rows = buf.shape[0];
    size_t cols = buf.shape[1];
    float* data_ptr = static_cast<float*>(buf.ptr);

    // 转成嵌套vector
    std::vector<std::vector<float>> vec_arr(rows, std::vector<float>(cols));
    for (size_t i = 0; i < rows; i++) {
        for (size_t j = 0; j < cols; j++) {
            vec_arr[i][j] = data_ptr[i * cols + j];
        }
    }

    // 此处可使用任意vector的方法操作vec_arr,比如push_back、sort等
    vec_arr[0].push_back(4.0f);
    std::sort(vec_arr[1].begin(), vec_arr[1].end());

    // 如需将修改同步回原numpy数组,遍历写回即可(注意如果修改了vector长度,要做对应维度校验)
    for (size_t i = 0; i < rows; i++) {
        for (size_t j = 0; j < cols; j++) {
            data_ptr[i * cols + j] = vec_arr[i][j];
        }
    }
}

3. 绑定与Python侧调用

函数绑定和普通pybind11函数一致:

PYBIND11_MODULE(numpy_utils, m) {
    m.def("modify_array", &modify_array, "修改二维float numpy数组");
}

Python侧直接传入numpy数组即可:

import numpy as np
import numpy_utils

arr = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], dtype=np.float32)
numpy_utils.modify_array(arr)
print(arr) # 可看到C++侧的修改已经同步到Python数组

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 20:45:08