Vas*_*ass 7 c++ matlab mex multidimensional-array
我试图索引为MATLAB编写外部c ++函数使用mex来操作矩阵,并且我无法使用多维索引.这里提供了一些示例,但我还没有找到如何解决下面描述的问题.我有一个样本矩阵:
>> mat
mat =
1 10
2 20
3 30
4 40
5 50
Run Code Online (Sandbox Code Playgroud)
目前我通过矩阵使用线性索引:
#include <mex.h>
#include <iostream>
using namespace std;
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
//1.get pointer to input graph_list and allocate it
double *graph_list = mxGetPr(prhs[0]);
mwSize mrows = mxGetM(prhs[0]);
mwSize ncols = mxGetN(prhs[0]);
cout<< mrows<<" rows\n";
cout<< ncols<<" cols\n";
int mm, nn;
for (nn=0;nn<ncols;nn++) {
for (mm=0;mm<mrows;mm++){
cout << graph_list[nn*(mrows) +mm] <<"\n";
}
}
}
Run Code Online (Sandbox Code Playgroud)
这会产生:
>> mexTryAlex(mat)
5 rows
2 cols
1
2
3
4
5
10
20
30
40
50
Run Code Online (Sandbox Code Playgroud)
当我更改graph_list的定义并尝试2D索引到graph_list时,会出现编译错误mex
:
double **graph_list = mxGetPr(prhs[0]);
cout << graph_list[nn][mm];
Run Code Online (Sandbox Code Playgroud)
编辑:这是收到的错误消息
>> mex mexTryAlex.cpp
Warning: You are using gcc version "4.4.3-4ubuntu5)". The version
currently supported with MEX is "4.3.4".
For a list of currently supported compilers see:
http://www.mathworks.com/support/compilers/current_release/
mexTryAlex.cpp: In function ‘void mexFunction(int, mxArray**, int, const mxArray**)’:
mexTryAlex.cpp:16: error: cannot convert ‘double*’ to ‘double**’ in initialization
mex: compile of ' "mexTryAlex.cpp"' failed.
??? Error using ==> mex at 208
Unable to complete successfully.
Run Code Online (Sandbox Code Playgroud)
编译器说明了一切.
在C中,2D数组就像一个数组数组.因此,2D阵列与1D阵列根本不同; 它是一个指针数组,其中每个元素都包含一个指向数组的指针(因此是一个双指针double**
).
你要求mxGetPr()
返回一个double**
,但它返回一个double*
,例如,指向一维数组的第一个元素的指针.该1D阵列只能线性索引.
我的猜测是MATLAB以这种方式做到这一点,以保持索引数组的一致性 - 你真的期望/想要double****
一个4-D阵列吗?
而且,mxGetPr()
不能通过返回类型重载(毕竟它是C).
为了能够对一维数组进行双重索引,你可以潜入一个小宏:
#define A(i,j) A[(i) + (j)*numrows]
Run Code Online (Sandbox Code Playgroud)
并像这样使用它
double *A = mxGetPr(...);
int numrows = 4; /* or get with mxGetM() or so) */
double blah = A(3,2); /* call to MACRO */
Run Code Online (Sandbox Code Playgroud)
显然,与所有宏一样,需要注意以下几点:
您可以编写一个函数来缓解这些缺点:
double getValue(double** array, int row, int* dims);
Run Code Online (Sandbox Code Playgroud)
(或者mxCalcSingleSubscript
像Shai所指出的那样使用),但这并没有真正提高表达能力恕我直言:
double blah = getValue(array, 3,4, dims);
/* or the ugliness from mxCalcSingleSubscript(); */
Run Code Online (Sandbox Code Playgroud)
你也可以写在C++中,做一个矩阵型类的operator()
,用指针和尺寸构建它mxGetPr()
和mxGetDims()
等,使用编译在Matlab g++
或同等学历,但引入了其他问题一大堆,并添加方式更加复杂比大多数情况需要的.
因此,为了避免所有这些混乱,我只是总是在原地计算索引:)
小智 7
具有矩阵类是解决此类问题的最简单方法.有很多可供选择,所以不要费心自己写.犰狳相当不错,如果你使用它也可以与LAPACK集成. http://arma.sourceforge.net/docs.html
见下面的例子
#include <mex.h>
#include <iostream>
#include <armadillo>
using namespace std;
using namespace arma;
//creates an armadillo matrix from a matlab matrix
mat armaMatrix(const mxArray *matlabMatrix[]){
mwSize mrows = mxGetM(matlabMatrix[0]);
mwSize ncols = mxGetN(matlabMatrix[0]);
double *values = mxGetPr(matlabMatrix[0]);
return mat(values, nrows, ncols);
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
mat graph_list = armaMatrix(prhs);
//print the matrix
cout << graph_list<<"\n";
//print the first column
cout << graph_list(span::all,0) <<"\n";
}
Run Code Online (Sandbox Code Playgroud)