【问题标题】:what's wrong with my mex-file?我的 mex 文件有什么问题?
【发布时间】:2013-06-25 15:06:02
【问题描述】:

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

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

【问题讨论】:

  • “来自不兼容指针类型的赋值” == 不正确。
  • 这个问题NOT“太宽泛”:它涉及mex 编程的几个 基本概念。我强烈投票支持重新开放!

标签: c matlab mex


【解决方案1】:

有几个问题:

  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*

【讨论】:

  • 感谢您帮助我。但是在你的建议之后,matlab 仍然崩溃:-(。
  • 谢谢。我是 matlab 上的 mex 文件的新手。我会尽快退房并返回。
【解决方案2】:

怎么了

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

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

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

修复它

函数mxGetPr 返回一个指针,指向由mxArray 表示的底层double 数组。

因此,

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

错误x 指向内存中的 64 位,表示 浮点 数,
但是当您以*x 访问它时,您是在告诉编译器将这些 64 位“读取”为 32 位 integer

还有一件事:你必须创建输出参数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 的说明操作即可。

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

【讨论】:

  • 感谢您的帮助。但是在您提出建议后,我的问题仍然存在。再次感谢。
  • 您的建议编译成功,matlab 不再崩溃(我什至没有警告)。但是当我运行我的代码时,无论我输入什么 A 和 B 值,答案总是 6!这很奇怪,不是吗?
  • @mad - 按照我的建议使用调试器。通过这种方式,您将学到 很多
  • 我发现了问题,第一个参数被给了两次。所以我改变了 double * y = mxGetPr(prhs[0]);加倍 * y = mxGetPr(prhs[1]);谢谢。
【解决方案3】:

这是一个示例实现:

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 函数来简化代码,它绕过了指针。

【讨论】:

  • 谢谢,它也有效。你知道关于 mex.h 函数的好教程吗?
  • 文档是一个好的开始。 MATLAB 附带了许多示例,您可以学习
猜你喜欢
  • 1970-01-01
  • 2012-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-21
  • 2014-09-04
  • 1970-01-01
相关资源
最近更新 更多