不能直接将 numpy.ndarray 传给 c++,因为它是带元数据的 python 对象,c++ 无法原生解析,易致段错误或乱码;须通过 pybind11::array 接收并确保 c-contiguous,避免隐式拷贝需用 forcecast(),内存生命周期必须由 pybind11 或显式引用管理。

为什么不能直接把 numpy.ndarray 传给 C++?
因为 Python 的 numpy.ndarray 是一个带元数据(shape、dtype、strides)的 Python 对象,而 C++ 没有原生机制理解它。直接传指针或对象会触发段错误或数据错位——常见报错是 Segmentation fault 或读出全零/乱码。
用 pybind11 导出 C++ 函数时怎么接收 NumPy 数组?
必须通过 pybind11::array 或 pybind11::buffer 接收,而不是裸指针或 std::vector。它会自动做内存视图映射,但要求数组是 C-contiguous(行优先连续)。
- 若输入数组不是连续的,先调用
arr.copy()或np.ascontiguousarray(arr) - 在 C++ 端用
pybind11::array_t<float></float>(按实际 dtype 替换float)接收 - 获取原始数据指针:用
.data(),别用.mutable_data()除非你要写入 - 获取 shape:用
.shape()返回std::vector<size_t></size_t>,注意索引是size_t不是int
如何避免 pybind11::array_t 构造时的隐式拷贝?
默认构造 pybind11::array_t<t></t> 会尝试复制数据;如果你只想读取且确保输入是连续的,加 pybind11::array::forcecast() 标志,并在 Python 侧提前检查:
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
import numpy as np arr = np.array([[1,2],[3,4]], dtype=np.float32) assert arr.flags.c_contiguous, "数组必须是 C 连续的" # 再传给 C++ 函数
C++ 侧声明示例:
py::array_t<float> process_array(py::array_t<float> input) {
auto buf = input.request();
float *ptr = static_cast<float>(buf.ptr);
// ……处理 ptr 和 buf.shape
}</float></float></float>
如果 C++ 代码已有固定接口(比如只接受 float* 和 int*),怎么办?
不能绕过 NumPy 的内存管理直接传裸指针——Python GC 可能在 C++ 还在用时回收数组。安全做法是:在 Python 层显式保持引用,或把数组转成 ctypes 指针并传生命周期控制权。
- 推荐方式:用
arr.__array_interface__['data'][0]获取地址,再用ctypes.cast(..., ctypes.POINTER(ctypes.c_float)) - 但必须确保
arr在整个 C++ 调用期间不被释放(例如把它作为函数参数外的局部变量长期持有) - 更稳妥的做法是用
pybind11封装一层,让它接管内存生命周期,而非手动管理
真正麻烦的从来不是“怎么传”,而是“谁负责释放、什么时候释放、是否允许修改”。多数崩溃都发生在假设 C++ 会 copy 数据,结果 Python 提前 del 了数组。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










