我的mex文件出了什么问题?

时间:2013-06-25 15:06:03

标签: c matlab mex

我正在尝试学习matlab和mex文件,并编写了以下用C语言编写的非常简单的代码,由matlab调用:

#include "mex.h"

void aplusb(int x, int y, int *z)
{
    z=x+y;
}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    int *x;
    int *y;
    int *z;


    if(nrhs<2) 
    {
       mexErrMsgIdAndTxt( "MATLAB:aplusb:invalidNumInputs", "Need 2 values to sum");
    } 

    else if(nlhs>2) 
    {
        mexErrMsgIdAndTxt( "MATLAB:aplusb:invalidNumInputs", "Need one value to return.");
    }

    z = mxGetPr(plhs[0]);
    x = mxGetPr(prhs[0]);
    y = mxGetPr(prhs[1]);

  aplusb(x,y,z);
}

问题

我可以使用mex aplusb.c正确编译代码。只返回一些警告:

aplusb.c:5:4: warning: assignment makes pointer from integer without a cast 
aplusb.c: in function ‘mexFunction’:
aplusb.c:25:5: warning: assignment from incompatible pointer type
aplusb.c:26:5: warning: assignment from incompatible pointer type
aplusb.c:27:5: warning: assignment from incompatible pointer type

但是当我运行调用.c文件的.m文件时,matlab会因分段违规而崩溃。

如果我的代码编译好了,我的代码出了什么问题?

3 个答案:

答案 0 :(得分:4)

有几个问题:

  1. aplusb中,应为*z=x+y;
  2. 调用方法时不传递指针:aplusb(*x,*y,z);
  3. aplusb的签名更改为:void aplusb(double x, double y, double *z) - 毕竟您将指针传递给double,编译器无法将double*转换为int*
  4. xyy更改为double* - 而不是int*。 mxGetPr返回double*,编译器无法将double*转换为int*

答案 1 :(得分:3)

出了什么问题

  1. aplusb中,您将两个整数的总和分配给指针z,而不是*z

  2. 无法访问输出参数mxGetPr(plhs[0])而不先分配它。

  3. mxGetPr会返回指向 double 而不是int的指针。您无法将指向double的指针投射到指向int的指针:您只能将double转换为int s。

  4. 修复它

    函数mxGetPr指针返回给由double表示的基础mxArray数组。

    因此,

    int * x = mxGetPr( prhs[0] );
    

    错误x指向记忆中的64位,表示浮点数字,
    但当你以*x的身份访问它时,你告诉编译器将这些64位“读取”为32位整数

    还有一件事:你必须创建输出参数plhs[0]

    正确的方法是

    double * x = mxGetPr(prhs[0]);
    double * y = mxGetPr(prhs[1]);
    int z;
    aplusb( *x /* cast double to int*/, *y /* cast double to int*/, &z ); // pass double and not poiners to double!
    // allocate output
    plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
    double *out = mxGetPr( plhs[0] );
    out[0] = z; // cast int to double
    

    你能做什么?

    为了使用此示例进行学习,您应调试mex文件 怎么做?只需按照说明here

    看看你是否可以使用debuger自己发现所有麻烦 - 这是最好的学习方法。

答案 2 :(得分:1)

以下是一个示例实现:

myadd.c

#include "mex.h"

void myadd(double x, double y, double *z)
{
    *z = x + y;
}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    double x, y, z;

    /* Check for proper number of arguments. */
    if(nrhs!=2) {
        mexErrMsgIdAndTxt("mex:invalidNumInputs", "Two inputs required.");
    } else if(nlhs>1) {
        mexErrMsgIdAndTxt("mex:maxlhs", "Too many output arguments.");
    }

    /* Check for correct inputs. */
    if( !mxIsDouble(prhs[0]) || !mxIsDouble(prhs[1]) ||
            mxIsComplex(prhs[0]) || mxIsComplex(prhs[1]) ||
            mxGetNumberOfElements(prhs[0])!=1 ||
            mxGetNumberOfElements(prhs[1])!=1) {
        mexErrMsgIdAndTxt("mex:inputNotRealScalarDouble",
                "Inputs must be noncomplex scalar doubles.");
    }

    /* extract input */
    x = mxGetScalar(prhs[0]);
    y = mxGetScalar(prhs[1]);

    /* call subroutine */
    myadd(x, y, &z);

    /* assign output */
    plhs[0] = mxCreateDoubleScalar(z);
}

MATLAB

>> mex myadd.c
>> myadd(10,20)
ans =
    30

请注意,我对输入参数的类型(标量非复数双精度)添加了适当的检查。如果输入不是这样,这可以避免崩溃MATLAB。

我还展示了如何通过使用MX函数的“标量”版本来简化代码,这会绕过指针。