【问题标题】:MATLAB mex routine does not return correct valueMATLAB mex 例程不返回正确的值
【发布时间】:2014-06-13 06:19:35
【问题描述】:

我正在尝试构建一个 C/C++ 函数供 MATLAB 调用。这是我的 C/C++ 代码:

#include "mex.h"

double* MyarrayProduct(double* a, double* b, int N)
{
    double* c = (double*)malloc(N*sizeof(double));
    double* pc = c;

    for (int n = 0; n < N; n++)
    {
        *pc = *a**b;
        pc++;
        a++;
        b++;
    }

    return c;
}

/* The gateway function */
void mexFunction(int nlhs, mxArray *plhs[],
                 int nrhs, const mxArray *prhs[])
{

    //------------------------------------------ Verify MEX-File Input and Output Parameters -----------------------------------------------------//
    //To check for two input arguments, multiplier and inMatrix, use this code.
    if(nrhs!=2) 
    {
        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs",
                      "Two inputs required.");
    }

    //Use this code to check for one output argument, the product outMatrix.
    if(nlhs!=1) 
    {
        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nlhs",
                          "One output required.");
    }

    if( !mxIsDouble(prhs[1]) || 
         mxIsComplex(prhs[1])) 
    {
        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notDouble",
            "Input matrix must be type double.");
    }

    /* check that number of rows in second input argument is 1 */
    if(mxGetM(prhs[1])!=1) 
    {
        mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notRowVector",
                          "Input must be a row vector.");
    }


    //------------------------------------------ variable declarations here ----------------------------------------//
    double *inMatrixA;      /* input scalar */
    double *inMatrixB;       /* 1xN input matrix */

    int ncols;           /* size of matrix */

    double *outMatrix;      /* output matrix */


    //------------------------------------------- read in data -----------------------------------------//
    /* get the value of the scalar input  */
    inMatrixA =  mxGetPr(prhs[0]);


    /* create a pointer to the real data in the input matrix  */
    inMatrixB = mxGetPr(prhs[1]);


    /* get dimensions of the input matrix */
    ncols = mxGetN(prhs[1]);


    //------------------------------------------- Prepare Output Data -----------------------------------------//
    /* create the output matrix */
    plhs[0] = mxCreateDoubleMatrix(1,ncols,mxREAL);

    /* get a pointer to the real data in the output matrix */
    outMatrix = mxGetPr(plhs[0]);

    /* call the computational routine */
    outMatrix = MyarrayProduct(inMatrixA,inMatrixB,ncols);


/* code here */
}

这是我的 MATLAB 结果。

>> a =[1 2 3]

a =

     1     2     3

>> b = [4 5 6]

b =

     4     5     6

>> mex MyarrayProduct.cpp
>> c = MyarrayProduct(a,b)

c =

     0     0     0

我进入了我的 C/C++ 代码,并在

找到
outMatrix = MyarrayProduct(inMatrixA,inMatrixB,ncols);

outMatrix 实际上是 4、10、18,这是正确的。但它似乎很难将结果发回。我想知道这里有什么问题?我无法在 mex 中返回指针?

【问题讨论】:

    标签: c++ matlab mex


    【解决方案1】:
    plhs[0] = mxCreateDoubleMatrix(1,ncols,mxREAL);
    

    mxCreateDoubleMatrix 调用上方的行已经为您分配了大小为1 x ncols 的矩阵。

    outMatrix = MyarrayProduct(inMatrixA,inMatrixB,ncols);
    

    您在这里所做的只是覆盖outMatrix 的值,即它指向的内存位置。您实际上并没有覆盖mxCreateDoubleMatrix 分配的内存。


    要解决此问题,请将您的 MyarrayProduct() 函数更改为:

    void MyarrayProduct(double* a, double* b, int N, double* pc)
    {
        for (int n = 0; n < N; n++)
        {
            *pc = *a**b;
            pc++;
            a++;
            b++;
        }
    }
    

    然后称它为

    /* call the computational routine */
    MyarrayProduct(inMatrixA,inMatrixB,ncols,outMatrix);
    

    另一个应该有效的解决方案是:

    /* create the output matrix */
    plhs[0] = mxCreateDoubleMatrix(1,0,mxREAL); // don't allocate any memory yet
    
    /* call the computational routine */
    outMatrix = MyarrayProduct(inMatrixA,inMatrixB,ncols);
    
    /* free the existing real array (in case MATLAB allocates a size 0 array) */
    mxFree(mxGetPr(plhs[0]));
    
    /* reassign the array in the matrix */
    mxSetPr(plhs[0], outMatrix);
    
    /* set the correct dimensions */
    mxSetN(plhs[0], ncols);
    

    但是,即使在这种情况下,我也会修改MyarrayProduct(),使其使用mxMalloc 而不是malloc。链接的 MathWorks 文档会警告您不要使用后者。

    在 MATLAB 应用程序中使用 mxMalloc 而不是 ANSI C malloc 函数来分配内存。

    【讨论】:

    • 我知道您的代码有效,但是这一行怎么样? /* 得到一个指向输出矩阵中真实数据的指针 */ outMatrix = mxGetPr(plhs[0]);这不是将 outMatrix 指向 plhs[0] 吗?那么如果 outMatrix 发生变化,plhs[0] 不应该也发生变化吗?
    • @Ono 不,您所做的只是重新分配指针,而不是复制指针指向的内容。这基本上就是您的代码所做的 - coliru.stacked-crooked.com/a/dbba1c936f3e1883
    猜你喜欢
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-09
    • 2021-10-26
    • 2015-10-13
    相关资源
    最近更新 更多