2

我正在尝试了解 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 会因分段违规而崩溃。

如果编译正常,我的代码有什么问题?

4

3 回答 3

4

有几个问题:

  1. aplusb,应该是*z=x+y;
  2. 调用方法时不要传递指针:aplusb(*x,*y,z);
  3. 将签名更改aplusb为此:void aplusb(double x, double y, double *z)-毕竟您将指针传递给双精度,并且编译器无法转换double*int*
  4. 改变x,成为y-不。mxGetPr 返回且编译器无法转换为ydouble*int*double*double*int*
于 2013-06-25T15:13:16.863 回答
3

怎么了

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

  2. 如果不先分配输出参数,您将无法访问它。mxGetPr(plhs[0])

  3. mxGetPr返回指向doubleand not的指针int。您不能将指向指针的指针转换double为指向 的指针int:您只能将doubles 转换为ints。

修复它

该函数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 文件
怎么做?只需按照此处的说明进行操作。

看看您是否可以使用调试器自己发现所有问题 - 这是最好的学习方式。

于 2013-06-25T15:09:08.457 回答
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 函数的“标量”版本来简化代码,它绕过了指针。

于 2013-06-25T16:15:19.577 回答