在matlab,C++联合编程的过程中,想使用一下Eigen库(一个C++矩阵运算库)。
为啥不直接用matlab的库呢?
有两点考虑:
- 1、matlab中写for循环太慢,处理图像块有时还得两层for循环
- 2、在C++中采用matlab函数,不利于生成独立的C++程序。
不多说了,上代码:
以下是将matlab矩阵转为Eigen中的Map(可以当做矩阵使用)的函数,转为Map而不是Matrix是为了避免不必要的数据拷贝(Eigen的数据共享实在是烂的可以!)
namespace Eigen {
template<typename T> Map<Matrix<T, Dynamic, Dynamic, ColMajor>> matlab2Eigen (const mxArray * pMat, bool needTranspose = true) {
Map< Matrix<T, Dynamic, Dynamic, ColMajor>> matrixMap ( (T*) mxGetPr (pMat), mxGetM (pMat), mxGetN (pMat) );
return matrixMap;
}
}
其实就是一行函数而已,也就是Eigen中Map 的基础用法。更多用法参见:
http://eigen.tuxfamily.org/dox/group__TutorialMapClass.html
其中的一行用于指定间隔的(注意这里列间距为1(更准确说是外间距,因为矩阵为列优先存储的,外间距为列间距),行间距为4,但矩阵是列优先存储的!也就是说,M(r,c)的计算方法为: M(c*1+r*4);)
Map<Matrix<int,2,4>, Unaligned, Stride<1,4> >(array) ;
如果是常用的写法:
Map<Matrix<int,2,4>>(array) ;
或者展开写:
Map<Matrix<int,2,4>, Unaligned, Stride<0,0> >(array) ;
M(r,c)的计算方法为: M(c*4+r*1)
附上完成的测试代码(两个矩阵相加):
#include <Eigen/Core>
//mex headers and libraries
#include "mex.h"
#pragma comment(lib,"libmx.lib")
#pragma comment(lib,"libmex.lib")
#pragma comment(lib,"libmat.lib")
namespace Eigen {
template<typename T> Map<Matrix<T, Dynamic, Dynamic, ColMajor>> matlab2Eigen (const mxArray * pMat, bool needTranspose = true) {
Map< Matrix<T, Dynamic, Dynamic, ColMajor>> matrixMap ( (T*) mxGetPr (pMat), mxGetM (pMat), mxGetN (pMat) );
return matrixMap;
}
}
//define function name in the DLL
#pragma comment(linker,"/EXPORT:mexFunction") //保证了DLL导出的函数名未经过修改,等效于使用.def文件
void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
/* 检查输入输出变量的个数 */
if (nrhs != 2) mexErrMsgTxt ("Two inputs required.");
else if (nlhs > 2) mexErrMsgTxt ("Too many output arguments");
auto m1 = Eigen::matlab2Eigen<double> (prhs[0]);
auto m2 = Eigen::matlab2Eigen<double> (prhs[1]);
if (m1.rows() != m2.rows() || m1.cols() != m2.cols() )
mexErrMsgTxt ("two matrix must be the same size.");
/* 为返回参数创建矩阵 */
plhs[0] = mxCreateNumericMatrix (m1.rows(), m1.cols(), mxDOUBLE_CLASS, mxREAL);
auto m3 = Eigen::matlab2Eigen<double> (plhs[0]);
m3 = m1 + m2;
}