我的mex文件有什么问题?输入/输出定义?

时间:2015-02-19 18:11:01

标签: c++ matlab mex

我正在尝试运行我在VS中用c ++编写的mex函数。它在MATLAB中成功编译但返回错误的值。我非常确定,我不是在阅读16×21输入矩阵gammas。谁能看到这里有什么问题?

void fun(double gammas[], int num1, int num2, int length, double a[])
{
...
}

void mexFunction(int nlhs, mxArray *plhs, int nrhs, const mxArray *prhs)
{
double *gammas, *a;
int num1, num2, length;
size_t mrows, mcols;
mrows = 4; mcols = 21;
length = 21;
plhs[0] = mxCreateDoubleMatrix((mSize)mrows, (mwSize)ncols, mxREAL);
gammas = mxGetPr(prhs[0]);
num1 = (int)*mxGetPr(prhs[1]);
num2 = (int)*mxGetPr(prhs[2]);
a = mxGetPr(plhs[0]);

fun(gammas, num1, num2, length, a);
}

当我在VS中的“main”而不是“mex”函数中调用“fun”并手动提供输入gamma时,我得到了正确的“a”。当我在MATLAB代码中调用生成的mex文件时,我收到错误的“a”。

2 个答案:

答案 0 :(得分:2)

作为输入转置矩阵以解决CitizenInsane pointed out的行/列主要差异的替代方法,您可以在MEX文件中处理转置。使用辅助C ++函数。您可以编写循环来复制元素,也可以只通过permute调用mexCallMATLAB。如下所示:

int permute2DMATtoC(mxArray*& matPermuted, const mxArray* mat)
{
    mxAssert(mxGetNumberOfDimensions(mat)<=3, "Requires 2D or 3D matrix.");

    mxArray *permuteRHSArgs[2];
    permuteRHSArgs[0] = const_cast<mxArray*>(mat);
    permuteRHSArgs[1] = mxCreateDoubleMatrix(1,3,mxREAL);

    mxGetPr(permuteRHSArgs[1])[0] = 2;
    mxGetPr(permuteRHSArgs[1])[1] = 1;
    mxGetPr(permuteRHSArgs[1])[2] = 3; // supports 2D and 3D

    return mexCallMATLAB(1, &matPermuted, 2, permuteRHSArgs, "permute");
}

使用:

mxArray *matPermuted;
permute2DMATtoC(matPermuted, prhs[0]); // matPermuted is MATLAB-managed
double *gammas = (double*)mxGetData(matPermuted);

注意:由于matPermuted由MATLAB管理,因此您不需要明确销毁它以回收资源,但是当您完成后,您可以根据需要执行此操作:

mxDestroyArray(matPermuted);

对于RGB,可能需要将像素顺序(RGB-RGB-RGB -...)转换为平面顺序(RRRR ...- GGGG ...- BBBB ...)。

答案 1 :(得分:2)

正如您对问题的评论所怀疑的那样,问题是由于matlab和c / c ++如何将数组元素作为内存中的1D数组进行线性存储。 Matlab使用column-major顺序,而C / C ++使用row-major

我不建议你在调用mex函数之前进行排列,而是在mex函数中进行排列。要么@chappjc通过调用permutemexCallMatlab调用,要么调用mxCalcSingleSubscript,从坐标(无论维度数量)返回matlab的线性索引。

旁注:需要确认并找回我读过的很棒的文章,但是matlab使用列主要排序,因为它更适合矩阵乘法(创建较少的页面默认值时访问内存缓存,因此更快)。再次需要确认 ...但至少这个组织更适合按列而不是按行访问...

修改

顺便说一句,一些简单的代码(C#)从maltab的基于零的线性索引(mxCalcSingleSubscript的反向)获取坐标:

private static int[] getCoordinatesFromMatlabLinearIndex(int index, int[] arrayDims)
{
    var ret = new int[count];            
    var count = arrayDims.Length;
    for (var k = 0; k < count; k++)
    {
       index = Math.DivRem(index, arrayDims[k], out ret[k]);
    }

    return ret;
}