如何将C++矩阵传入Python并作为Numpy数组使用?
在C++中通过pybind11传递矩阵到Python(Numpy数组形式)并接收返回结果
1. Python侧准备
先编写一个接收Numpy数组并返回处理结果的函数,保存为matrix_ops.py:
import numpy as np def process_matrix(arr): # 示例:将输入矩阵元素乘以2后返回 return arr * 2
2. C++端实现
2.1 核心思路
利用pybind11的py::array_t封装C矩阵数据(自动适配buffer protocol),直接传递给Python函数;接收返回的Numpy数组后,通过py::buffer_info提取数据到C结构中。
2.2 完整代码
#include <pybind11/pybind11.h> #include <pybind11/numpy.h> #include <vector> #include <iostream> namespace py = pybind11; int main() { // 初始化Python解释器,必须放在所有pybind11操作之前 py::scoped_interpreter guard{}; try { // 加载Python模块 py::module_ ops_module = py::module_::import("matrix_ops"); // 获取目标处理函数 py::object process_func = ops_module.attr("process_matrix"); // 构造C++端矩阵(用连续内存存储,匹配Numpy的内存布局) const int rows = 3; const int cols = 3; std::vector<float> matrix_data(rows * cols); // 填充测试数据:1~9的3x3矩阵 for (int idx = 0; idx < rows * cols; ++idx) { matrix_data[idx] = idx + 1.0f; } // 将C++数据包装为Numpy数组 // 若需确保C++数据生命周期与数组绑定,可添加第三个参数py::cast(matrix_data) py::array_t<float> np_matrix({rows, cols}, matrix_data.data()); // 调用Python函数并获取返回值 py::object result_obj = process_func(np_matrix); // 把返回的Python对象转为Numpy数组 py::array_t<float> result_np = py::cast<py::array_t<float>>(result_obj); // 获取数组的buffer信息(内存指针、形状等) py::buffer_info buf_info = result_np.request(); float* result_data = static_cast<float*>(buf_info.ptr); int result_rows = buf_info.shape[0]; int result_cols = buf_info.shape[1]; // 打印验证结果 std::cout << "处理后的矩阵:" << std::endl; for (int i = 0; i < result_rows; ++i) { for (int j = 0; j < result_cols; ++j) { std::cout << result_data[i * result_cols + j] << " "; } std::cout << std::endl; } } catch (const py::error_already_set& e) { std::cerr << "Python执行错误:" << e.what() << std::endl; return 1; } return 0; }
2.3 关键细节说明
- 内存管理:如果C数据会在Numpy数组使用期间被释放,构造
py::array_t时需添加py::cast(matrix_data)作为第三个参数,通过keep_alive机制确保C容器的生命周期覆盖Numpy数组。 - Buffer Protocol适配:
py::array_t已内置实现buffer protocol,Python侧的Numpy可直接识别,无需手动构建底层buffer对象。 - 错误处理:捕获
py::error_already_set可获取Python侧抛出的异常信息,方便调试。
3. 编译运行
用CMake构建的示例配置(CMakeLists.txt):
cmake_minimum_required(VERSION 3.14) project(cpp_py_matrix) find_package(pybind11 REQUIRED) add_executable(cpp_py_matrix main.cpp) target_link_libraries(cpp_py_matrix PRIVATE pybind11::embed)
编译完成后,确保matrix_ops.py在可执行文件的同级目录,直接运行即可看到输出。
内容的提问来源于stack exchange,提问作者Victor M
相关产品推荐
相关产品推荐

