如何通过boost::python将Python缓冲区(如numpy数组)传入C++
实现Python向C++传递numpy数组并遍历打印的方案
我之前做过类似的需求,用pybind11来实现是最简洁高效的,它对Python的缓冲区协议支持非常完善,能直接把numpy数组映射到C++的内存结构里,不用手动处理底层的Py_buffer细节。下面是完整的实现步骤:
1. 准备依赖
首先安装pybind11,用pip直接装最方便:
pip install pybind11
2. 编写C++模块代码
创建一个名为mymod.cpp的文件,代码如下:
#include <pybind11/pybind11.h> #include <pybind11/numpy.h> #include <iostream> namespace py = pybind11; void some_func(py::array_t<int> arr) { // 请求数组的只读访问权限 py::buffer_info buf = arr.request(); // 获取数组的指针和总长度 int* ptr = static_cast<int*>(buf.ptr); size_t len = buf.size; // 遍历并打印元素 std::cout << "数组元素:"; for (size_t i = 0; i < len; ++i) { std::cout << ptr[i]; if (i != len - 1) { std::cout << ", "; } } std::cout << std::endl; } // 绑定模块和函数 PYBIND11_MODULE(mymod, m) { m.def("some_func", &some_func, "接收numpy数组并打印元素"); }
代码说明
py::array_t<int>:直接指定接收int类型的numpy数组,pybind11会自动校验输入类型是否匹配arr.request():获取数组的核心缓冲区信息,包括内存指针、元素总数、维度尺寸等- 用指针遍历数组的逻辑和C++操作普通数组完全一致,没有额外学习成本
如果要处理其他数值类型(比如float),只需要把py::array_t<int>改成py::array_t<float>,int* ptr改成float* ptr即可。
3. 编写编译脚本
创建setup.py文件,用来把C++代码编译成Python可导入的模块:
from setuptools import setup, Extension import pybind11 ext_modules = [ Extension( "mymod", ["mymod.cpp"], include_dirs=[pybind11.get_include()], language="c++", extra_compile_args=["-O3"], ), ] setup( name="mymod", ext_modules=ext_modules, )
4. 编译并测试
在终端执行编译命令:
python setup.py build_ext --inplace
编译完成后,就可以用你提供的Python代码测试了:
import mymod import numpy as np mymod.some_func(np.array([1,2,3]))
运行后会输出:
数组元素:1, 2, 3
进阶:处理多维数组
如果需要接收二维数组(比如np.array([[1,2],[3,4]])),可以通过buf.shape获取各维度尺寸,示例代码如下:
void some_func(py::array_t<int> arr) { py::buffer_info buf = arr.request(); // 获取二维数组的行数和列数 size_t rows = buf.shape[0]; size_t cols = buf.shape[1]; int* ptr = static_cast<int*>(buf.ptr); // 遍历二维数组 for (size_t i = 0; i < rows; ++i) { for (size_t j = 0; j < cols; ++j) { // 假设数组是连续存储的,计算元素位置 std::cout << ptr[i * cols + j] << " "; } std::cout << std::endl; } }
内容的提问来源于stack exchange,提问作者gct
相关产品推荐
相关产品推荐

