如何对元素为矩阵的嵌套矩阵正确使用Eigen::Map?
问题背景
需要编写C/C++ DLL封装接口,调用重度依赖Eigen的第三方库,要求不修改库源码,通过Eigen::Map完成库内Eigen矩阵和DLL对外C风格数组的转换。目前输入侧映射已正常运行,但输出为4×1的嵌套矩阵(元素为3×4 double矩阵),现有实现通过for循环完成输出映射,希望移除循环直接用Eigen::Map实现。
现有可运行的最小示例代码:
#include <Eigen/Dense> using namespace Eigen; void matrix_test(double* in, double* out) { // 输入数组映射为3x3矩阵,匹配内存布局 Map<Matrix<double, 3, 3>, 0, Stride<1, 3>> matrix_in(in, 3, 3); // 此处调用第三方库,输入matrix_in,填充输出到matrix_out Matrix<Matrix<double, 3, 4>, 4, 1> matrix_out; // 现有循环实现:将嵌套矩阵映射到输出数组 for (int i=0; i < 4; i++) { Map<Matrix<double, 3, 4, RowMajor>>((out + i * (3 * 4)), 3, 4) = matrix_out(i); } }
实现方案
直接替换整个for循环为一行Map赋值即可,和原有循环语义完全一致:
Map<Matrix<Matrix<double, 3, 4, RowMajor>, 4, 1>, 0>(out) = matrix_out;
说明
- 目标Map的类型和输出内存布局完全匹配:外层为4×1列优先存储的矩阵,4个内层3×4行优先矩阵连续排布,无内存空隙,和循环中逐块映射的内存位置完全一致。
- 第二个模板参数传
0代表不要求内存对齐,和输入侧Map的配置保持一致,兼容C风格接口传入的无对齐保证的数组指针,避免内存访问错误。 - 赋值过程Eigen会自动完成内层矩阵从默认列优先到输出要求的行优先的存储顺序转换,和逐块循环赋值的行为完全一致,编译器开启O2及以上优化时会自动展开拷贝逻辑,无额外性能开销。
修改后的完整代码如下:
#include <Eigen/Dense> using namespace Eigen; void matrix_test(double* in, double* out) { // 输入数组映射为3x3矩阵,匹配内存布局 Map<Matrix<double, 3, 3>, 0, Stride<1, 3>> matrix_in(in, 3, 3); // 此处调用第三方库,输入matrix_in,填充输出到matrix_out Matrix<Matrix<double, 3, 4>, 4, 1> matrix_out; // 直接映射嵌套矩阵到输出C数组,无需循环 Map<Matrix<Matrix<double, 3, 4, RowMajor>, 4, 1>, 0>(out) = matrix_out; }
注意事项
- 该方案仅适用于内层矩阵为编译期固定大小的场景:本示例中3×4为固定维度,Eigen可以在编译期计算所有内存偏移,无动态内存开销。如果内层矩阵是动态大小,嵌套矩阵内存不保证连续,不能使用该方法。
- 3×4 double矩阵总大小为96字节,是Eigen默认对齐边界(16/32字节)的整数倍,内外层矩阵之间不会产生内存填充字节,内存布局完全连续,映射操作安全。
内容的提问来源于stack exchange,提问作者F. Althaus
相关产品推荐
相关产品推荐

