Cython中如何将Numpy矩阵列表映射为Eigen矩阵std::vector
解决方案
第一步:修复C++头文件的类型声明错误
你的第一个编译错误是C侧找不到FlattenedMapWithOrder,本质是Cython层面的FlattenedMapWithOrder是eigency提供的语法糖,C原生侧没有这个类型名,我们直接在C++侧用原生Eigen类型声明函数即可,避免和eigency的内部类型耦合。
修改后的cpp_source_cpp.h对应部分如下:
// 保留原有头文件引入,仅修改函数声明 float MyCppFunction( const Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>& inputMatrix ); // 直接用Eigen::Map的vector作为参数类型 float MyCppFunctionVector( const std::vector<Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>>& inputMatrixList );
第二步:修改Cython侧的函数声明和实现
C不允许不同模板参数的std::vector直接隐式转换(哪怕元素类型可转换也不行),所以我们直接把Cython侧vector的元素类型声明为和C侧对齐的Eigen Map类型,单个FlattenedMapWithOrder实例可以隐式转换为Eigen Map,循环插入的时候完成转换即可。
修改cython_source.pyx的对应部分:
# 保留原有引入,修改外部函数声明 cdef extern from "source_cpp_cython/cpp_source_cpp.h": cdef float _MyCppFunction "MyCppFunction"( FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor] & ) # 声明参数为Eigen Map类型的vector cdef float _MyCppFunctionVector "MyCppFunctionVector"( vector[Map[Matrix, float, Dynamic, Dynamic, RowMajor]] & ) # 单矩阵函数保持原有实现不变 def my_python_function(np.ndarray[ndim=2, dtype=np.float32_t] my_matrix): cdef FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor] my_matrix_cpp my_matrix_cpp = FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor](my_matrix) return _MyCppFunction(my_matrix_cpp) # 修改列表处理函数的实现 def my_python_function_vector(list my_matrix_list): # vector元素类型和C++函数要求对齐 cdef vector[Map[Matrix, float, Dynamic, Dynamic, RowMajor]] matrix_map_vec cdef FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor] my_matrix_cpp for my_matrix in my_matrix_list: my_matrix_cpp = FlattenedMapWithOrder[Matrix, float, Dynamic, Dynamic, RowMajor](my_matrix) # 单个实例隐式转换为Eigen Map后插入vector matrix_map_vec.push_back(my_matrix_cpp) return _MyCppFunctionVector(matrix_map_vec)
第三步:修改C++侧的函数实现
现在C++侧接收的参数已经是原生Eigen Map的vector,不需要额外转换,直接使用即可:
修改cpp_source_cpp.cpp的对应部分:
#include "cpp_source_cpp.h" float MyCppFunction( const Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>& inputMatrix ) { return 5.0; } float MyCppFunctionVector( const std::vector<Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>>& inputMatrixList ) { // 直接使用inputMatrixList执行业务逻辑即可 return 6.0; }
原理说明
C中std::vector<T>和std::vector<U>是完全独立的两个类型,哪怕T可以隐式转换为U,两个vector类型之间也没有任何内置转换关系,这是你之前类型不匹配报错的核心原因。而单个eigency::FlattenedMap实例可以隐式转换为Eigen::Map,所以只需要在插入vector的时候完成单个元素的转换,让整个vector的元素类型和C函数要求的类型完全对齐即可。
内容的提问来源于stack exchange,提问作者Stefan
相关产品推荐
相关产品推荐

