Cython对接C++ std::array类型的优选实现方案是什么
Cython 绑定
std::array的成熟落地方案 截至目前最新的Cython 3.x稳定版本,官方依然没有提供std::array的通用封装,核心限制是暂不支持非类型模板参数的通用声明,但固定长度、固定元素类型的std::array绑定非常简单,是目前生产环境普遍使用的方案,不需要复杂的hack操作。
针对你给出的std::array<double,3>场景,实现要点如下:
- 首先通过Cython的类型字符串映射能力,单独声明需要用到的特化版本
std::array,不需要做通用模板适配 - 补全C++结构体的成员声明
- 实现getter/setter时做好内存映射、输入校验和数据拷贝,同时修正原代码框架的内存释放错误
完整可运行代码实现
以下是补全后的Cython代码(假设文件名为example.pyx):
# 导入numpy C接口,需要提前安装numpy依赖 cimport numpy as cnp # 初始化numpy C API,调用numpy相关C接口前必须执行 cnp.import_array() cdef extern from "<array>" namespace "std": # 把C++类型std::array<double,3>映射为Cython内部可用的类型名array_double3 cdef cppclass array_double3 "std::array<double, 3>": double& operator[](size_t idx) # 支持下标访问元素 double* data() # 获取底层连续内存指针 size_t size() # 获取数组固定长度 cdef extern from "ex.hpp": cdef cppclass example: double a int b array_double3 c # 直接用上面声明的特化类型声明成员即可 cdef class pyExample: cdef example *_cppExample def __cinit__(self): self._cppExample = new example() # 注意原框架这里方法名写错了,必须是__dealloc__(双下划线结尾),否则会触发内存泄漏 def __dealloc__(self): del self._cppExample @property def c(self): # 基于std::array的底层内存直接构造numpy数组,无拷贝,性能最优 cdef cnp.npy_intp shape[1] shape[0] = 3 cdef cnp.ndarray[double, ndim=1] arr = cnp.PyArray_SimpleNewFromData( 1, shape, cnp.NPY_DOUBLE, self._cppExample.c.data() ) # 绑定numpy数组的生命周期到当前pyExample实例,避免实例被提前回收导致悬垂指针 cnp.PyArray_SetBaseObject(arr, self) return arr @c.setter def c(self, pyArr): # 自动把Python列表、元组、numpy数组等输入转为C连续的double类型数组 cdef cnp.ndarray[double, ndim=1, mode="c"] arr = cnp.PyArray_FROM_OTF( pyArr, cnp.NPY_DOUBLE, cnp.NPY_ARRAY_C_CONTIGUOUS ) if arr.shape[0] != 3: raise ValueError("成员c必须是长度为3的数值序列") # 逐元素拷贝数据到底层C++数组成员 cdef size_t i for i in range(3): self._cppExample.c[i] = arr[i]
补充说明
- 如果项目中需要用到其他类型、其他长度的
std::array,只需要按照同样的格式在extern块里加对应的特化声明即可,比如std::array<int, 2>就写cdef cppclass array_int2 "std::array<int, 2>",按需声明即可,维护成本很低 - 如果不需要返回numpy数组,getter可以直接构造Python列表返回:
return [self._cppExample.c[i] for i in range(3)],只是会有数据拷贝的性能开销 - 这种写法从Cython 0.29版本开始就完全支持,不存在兼容性问题,是目前绑定固定长度
std::array的标准做法
内容的提问来源于stack exchange,提问作者Eney
相关产品推荐
相关产品推荐

