我正在尝试学习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会因分段违规而崩溃。
如果我的代码编译好了,我的代码出了什么问题?
答案 0 :(得分:4)
有几个问题:
aplusb
中,应为*z=x+y;
aplusb(*x,*y,z);
aplusb
的签名更改为:void aplusb(double x, double y, double *z)
- 毕竟您将指针传递给double,编译器无法将double*
转换为int*
x
,y
和y
更改为double*
- 而不是int*
。 mxGetPr返回double*
,编译器无法将double*
转换为int*
答案 1 :(得分:3)
在aplusb
中,您将两个整数的总和分配给指针z
,而不是*z
。
您无法访问输出参数mxGetPr(plhs[0])
而不先分配它。
mxGetPr
会返回指向 double
而不是int
的指针。您无法将指向double
的指针投射到指向int
的指针:您只能将double
转换为int
s。
函数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)
以下是一个示例实现:
#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);
}
>> mex myadd.c
>> myadd(10,20)
ans =
30
请注意,我对输入参数的类型(标量非复数双精度)添加了适当的检查。如果输入不是这样,这可以避免崩溃MATLAB。
我还展示了如何通过使用MX函数的“标量”版本来简化代码,这会绕过指针。