我应该如何将数据传递给 mexFunction 的 mxArray *plhs[] 以便在 Matlab 中获得其输出?
How should I pass data to mxArray *plhs[] of mexFunction in order to get its outputs in Matlab?
我想要一个预编译函数 returns 二次方程的最大正实根,如果它有任何正根,如果没有 returns 0。我正在使用一些远程传感数据,我做了一些测试,现在我的案例中的所有二次多项式都有实根,但不能确定它们的符号。所以我写了下面的C源代码。
/*
* mx_solve_quadratic.cpp
*
* Solves for real roots of the standard quadratic equation
*
* The calling syntax is:
*
* MaxRoot = mx_solve_quadratic(coefficientMatrix)
*
* This is a MEX file for MATLAB.
*/
#include <math.h>
#include "mex.h"
#include "matrix.h"
int gsl_poly_solve_quadratic (double , double , double , double *, double *);
/* The gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double a; /* coefficient for x^2 */
double b; /* coefficient for x */
double c; /* coefficient for 1 */
double x0; /* the smaller root */
double x1; /* the bigger root */
double *inMatrix = NULL;
inMatrix = mxGetPr(prhs[0]);
a = inMatrix[0];
b = inMatrix[1];
c = inMatrix[2];
int i = gsl_poly_solve_quadratic(a,b,c,&x0,&x1);
double signRoot = (x1 > 0 ? x1 : 0);
mxSetPr(plhs[0], &signRoot);
}
int gsl_poly_solve_quadratic (double a, double b, double c, double *x0, double *x1)
{
if (a == 0) /* Handle linear case */
{
if (b == 0)
{
return 0;
}
else
{
*x0 = -c / b;
return 1;
};
}
{
double disc = b * b - 4 * a * c;
if (disc > 0)
{
if (b == 0)
{
double r = sqrt (-c / a);
*x0 = -r;
*x1 = r;
}
else
{
double sgnb = (b > 0 ? 1 : -1);
double temp = -0.5 * (b + sgnb * sqrt (disc));
double r1 = temp / a ;
double r2 = c / temp ;
if (r1 < r2)
{
*x0 = r1 ;
*x1 = r2 ;
}
else
{
*x0 = r2 ;
*x1 = r1 ;
}
}
return 2;
}
else if (disc == 0)
{
*x0 = -0.5 * b / a ;
*x1 = -0.5 * b / a ;
return 2 ;
}
else
{
return 0;
}
}
}
事实上,我希望 signRoot
作为标量值返回给 MATLAB。我已经调试了两次代码:
a=[1 3 2];
b=mx_solve_quadratic(a)
a=[1 -3 2];
b=mx_solve_quadratic(a)
我看到一切正常,直到最后一行,我想将 signRoot
作为输出传递。如果我按 F10
,我会收到错误消息:
或者,如果我尝试 运行 MATLAB 中的 mex 函数而不进行调试,我将得到:
Suever 是正确的。您试图传递一个在 C 中创建的数组并将其传递给 MATLAB,这是不明智和未定义的行为。您必须做的是使用任何 mxCreate*
函数并将内存位置设置为您想要的任何结果。最简单的方法是使用 mxCreateDoubleMatrix
并指定输出有 1 行、1 列(即标量)并确保输出是真实的。
因此,做这样的事情来替换你的 mexFunction
:
中的最后一行代码
plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
double *out = mxGetPr(plhs[0]);
*out = signRoot;
这首先在 MATLAB 端为单个标量分配内存。然后你得到一个指向这个内存的指针,然后相应地设置它。
为了绝对确定我们在同一页面上,下面是 mexFunction
修改后的样子。请注意,更改的行是用 /* NEW */
注释引用的。
/* The gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double a; /* coefficient for x^2 */
double b; /* coefficient for x */
double c; /* coefficient for 1 */
double x0; /* the smaller root */
double x1; /* the bigger root */
double *inMatrix = NULL;
inMatrix = mxGetPr(prhs[0]);
a = inMatrix[0];
b = inMatrix[1];
c = inMatrix[2];
int i = gsl_poly_solve_quadratic(a,b,c,&x0,&x1);
double signRoot = (x1 > 0 ? x1 : 0);
plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); /* NEW */
double *out = mxGetPr(plhs[0]); /* NEW */
*out = signRoot; /* NEW */
}
运行 上面的代码和你的两个示例输入现在给出:
>> a = [1 -3 2];
>> b = mx_solve_quadratic(a)
b =
2
>> a = [1 3 2];
>> b = mx_solve_quadratic(a)
b =
0
我想要一个预编译函数 returns 二次方程的最大正实根,如果它有任何正根,如果没有 returns 0。我正在使用一些远程传感数据,我做了一些测试,现在我的案例中的所有二次多项式都有实根,但不能确定它们的符号。所以我写了下面的C源代码。
/*
* mx_solve_quadratic.cpp
*
* Solves for real roots of the standard quadratic equation
*
* The calling syntax is:
*
* MaxRoot = mx_solve_quadratic(coefficientMatrix)
*
* This is a MEX file for MATLAB.
*/
#include <math.h>
#include "mex.h"
#include "matrix.h"
int gsl_poly_solve_quadratic (double , double , double , double *, double *);
/* The gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double a; /* coefficient for x^2 */
double b; /* coefficient for x */
double c; /* coefficient for 1 */
double x0; /* the smaller root */
double x1; /* the bigger root */
double *inMatrix = NULL;
inMatrix = mxGetPr(prhs[0]);
a = inMatrix[0];
b = inMatrix[1];
c = inMatrix[2];
int i = gsl_poly_solve_quadratic(a,b,c,&x0,&x1);
double signRoot = (x1 > 0 ? x1 : 0);
mxSetPr(plhs[0], &signRoot);
}
int gsl_poly_solve_quadratic (double a, double b, double c, double *x0, double *x1)
{
if (a == 0) /* Handle linear case */
{
if (b == 0)
{
return 0;
}
else
{
*x0 = -c / b;
return 1;
};
}
{
double disc = b * b - 4 * a * c;
if (disc > 0)
{
if (b == 0)
{
double r = sqrt (-c / a);
*x0 = -r;
*x1 = r;
}
else
{
double sgnb = (b > 0 ? 1 : -1);
double temp = -0.5 * (b + sgnb * sqrt (disc));
double r1 = temp / a ;
double r2 = c / temp ;
if (r1 < r2)
{
*x0 = r1 ;
*x1 = r2 ;
}
else
{
*x0 = r2 ;
*x1 = r1 ;
}
}
return 2;
}
else if (disc == 0)
{
*x0 = -0.5 * b / a ;
*x1 = -0.5 * b / a ;
return 2 ;
}
else
{
return 0;
}
}
}
事实上,我希望 signRoot
作为标量值返回给 MATLAB。我已经调试了两次代码:
a=[1 3 2];
b=mx_solve_quadratic(a)
a=[1 -3 2];
b=mx_solve_quadratic(a)
我看到一切正常,直到最后一行,我想将 signRoot
作为输出传递。如果我按 F10
,我会收到错误消息:
或者,如果我尝试 运行 MATLAB 中的 mex 函数而不进行调试,我将得到:
Suever 是正确的。您试图传递一个在 C 中创建的数组并将其传递给 MATLAB,这是不明智和未定义的行为。您必须做的是使用任何 mxCreate*
函数并将内存位置设置为您想要的任何结果。最简单的方法是使用 mxCreateDoubleMatrix
并指定输出有 1 行、1 列(即标量)并确保输出是真实的。
因此,做这样的事情来替换你的 mexFunction
:
plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
double *out = mxGetPr(plhs[0]);
*out = signRoot;
这首先在 MATLAB 端为单个标量分配内存。然后你得到一个指向这个内存的指针,然后相应地设置它。
为了绝对确定我们在同一页面上,下面是 mexFunction
修改后的样子。请注意,更改的行是用 /* NEW */
注释引用的。
/* The gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double a; /* coefficient for x^2 */
double b; /* coefficient for x */
double c; /* coefficient for 1 */
double x0; /* the smaller root */
double x1; /* the bigger root */
double *inMatrix = NULL;
inMatrix = mxGetPr(prhs[0]);
a = inMatrix[0];
b = inMatrix[1];
c = inMatrix[2];
int i = gsl_poly_solve_quadratic(a,b,c,&x0,&x1);
double signRoot = (x1 > 0 ? x1 : 0);
plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL); /* NEW */
double *out = mxGetPr(plhs[0]); /* NEW */
*out = signRoot; /* NEW */
}
运行 上面的代码和你的两个示例输入现在给出:
>> a = [1 -3 2];
>> b = mx_solve_quadratic(a)
b =
2
>> a = [1 3 2];
>> b = mx_solve_quadratic(a)
b =
0