如何通过pybind11传递自定义结构体numpy数组调用C++ API
问题根因
报错的核心原因是你传入的numpy数组是dtype=object的对象数组,存储的是Ohlc Python类实例的引用,和你通过PYBIND11_NUMPY_DTYPE注册的结构体布局的numpy结构化数组类型不匹配。
修复步骤
1. 补全numpy dtype注册逻辑
你的Ohlc结构体中包含volume字段,但PYBIND11_NUMPY_DTYPE注册时没有包含该字段,会导致内存布局不匹配,先修正这部分C++代码:
// 原有错误代码 PYBIND11_NUMPY_DTYPE(Ohlc, open, high, low, close); // 修正为,补上volume字段 PYBIND11_NUMPY_DTYPE(Ohlc, open, high, low, close, volume);
重新编译安装你的pybind模块。
2. Python侧构造符合要求的结构化数组
不要直接用np.array([Ohlc()])生成对象数组,而是基于pybind注册的dtype生成结构化数组:
from ema_calculator_pybind11 import * import numpy as np # 获取pybind注册的Ohlc对应numpy dtype ohlc_dtype = np.dtype(Ohlc) # 按字段顺序传入数值构造结构化数组,顺序对应open、high、low、close、volume ohlc_arr = np.array( [(1.1, 2.2, 0.9, 1.5, 100), (1.5, 2.5, 1.2, 2.0, 200)], dtype=ohlc_dtype ) # 调用函数即可正常运行 calculate_ema(ohlc_arr)
原理解释
- 你通过
py::class_绑定的OhlcPython类,和PYBIND11_NUMPY_DTYPE注册的numpy结构化dtype是两套独立的类型体系,直接把Ohlc类实例塞进numpy数组会生成object类型数组,无法匹配py::array_t<Ohlc>的类型要求。 - 内置类型比如
double不会出现这个问题,是因为numpy原生double数组的布局和pybind要求的布局天然匹配,不需要走对象封装逻辑。 - 单个
Ohlc对象可以正常传参,是因为走的是py::class_绑定的类型检查逻辑,和numpy数组的参数检查逻辑无关。
内容的提问来源于stack exchange,提问作者user3036846
相关产品推荐
相关产品推荐

