我想从 matlab 运行两个名为“hello1.c”和“hello2.c”的 C 程序。
我的hello1.c
代码如下:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <mex.h>
#include <math.h>
#include "matrix.h"
void funcc(double **f, double **x, long n, long b, double lambda, double theta)
{
long i;
long j;
double u,v,y,z,w;
y = theta*lambda;
w = lambda*lambda;
z = 0.5*(theta+1.0)*w;
u = 0.0;
for(i=0;i<n;i++)
{
for(j=0;j<b;j++)
v = fabs(x[i][j]);
if (v <= lambda)
u += lambda*v;
else if (v > y)
u += z;
else
u += 0.5*(v*(2*y - v) - w)/(theta-1.0);
}
**f = u;
return;
}
void mexFunction (int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
/*set up input arguments */
double **x = mxGetPr(prhs[0]);
long n = (long)mxGetScalar(prhs[1]);
long b = (long)mxGetScalar(prhs[2]);
double lambda = mxGetScalar(prhs[3]);
double theta = mxGetScalar(prhs[4]);
int type = (int)mxGetScalar(prhs[5]);
double **f;
/* set up output arguments */
plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);
f=mxGetPr(plhs[0]);
funcc(f, x, n, b, lambda, theta);
}
我的hello2.c
代码如下:
long mymin(double *x, long n)
{
long i, ind;
double temp;
temp = x[0];
ind = 0;
for (i=1;i<n;i++)
{
if (x[i] < temp)
{
ind = i;
temp = x[i];
}
}
return ind;
}
void funnn(double *x, double *d, long n, long b, double lambda, double theta)
{
long i;
long j;
double u,z,w;
double xtemp[3],ytemp[3];
z = theta*lambda;
w = lambda*lambda;
for(i=0;i<n;i++)
{
for(j=0;j<b;j++)
u = fabs(d[j*n + i]);
xtemp[0] = min(lambda,max(0,u - lambda));
xtemp[1] = min(z,max(lambda,(u*(theta-1.0)-z)/(theta-2.0)));
xtemp[2] = max(z,u);
ytemp[0] = 0.5*(xtemp[0] - u)*(xtemp[0] - u) + lambda*xtemp[0];
ytemp[1] = 0.5*(xtemp[1] - u)*(xtemp[1] - u) + 0.5*(xtemp[1]*(-xtemp[1] + 2*z) - w)/(theta-1.0);
ytemp[2] = 0.5*(xtemp[2] - u)*(xtemp[2] - u) + 0.5*(theta+1.0)*w;
x[j*n + i] = xtemp[mymin(ytemp,3)];
x[j*n + i] = d[j*n + i]>= 0 ? x[j*n + i] : -x[j*n + i];
}
//return;
}
void mexFunction (int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
/*set up input arguments */
double* d = mxGetPr(prhs[0]);
long n = (long)mxGetScalar(prhs[1]);
long b = (long)mxGetScalar(prhs[2]);
double lambda = mxGetScalar(prhs[3]);
double theta = mxGetScalar(prhs[4]);
double *x;
/* set up output arguments */
plhs[0] = mxCreateDoubleMatrix(n,b,mxREAL);
x=mxGetPr(plhs[0]);
funnn(x, d, n, b, lambda, theta);
}
问题是,当我编译 MATLAB 代码时,它会调用我的 C 函数(当然我已经编写了 mex hello1.c
和 mex hello2.c
),MATLAB 返回屏幕,显示 MATLAB 遇到内部问题,需要关闭。事实上,这个错误是在 MEX 文件运行时检测到的。
这是因为我的函数mexFunction
写得不正确吗?任何知道如何编写 MEX 函数的人都可以帮助我吗?
任何帮助将不胜感激!
最佳答案
对于hello1.c
,mxGetPr
在 MEX 中不给你一个双指针。它为您提供一个单个指针,对于 2D 内存,它采用列主布局。您必须通过以下语法访问 2D 数组中的正确值,假设 i
和 j
是您要访问的 2D 数组中的行和列:
ind = j*rows + i;
...因此,如果您想在 2D 数组 x
中找到位置 (i,j)
,只需执行以下操作:
double val = x[j*rows + i];
rows
是二维数组中的总行数。因此,您必须在代码中更正此问题才能正确访问二维数组。您还必须对 f
执行相同的操作。此外,您在第二个 for
循环周围缺少一对大括号,稍后我将解释原因。
因此,您的函数变为:
void funcc(double *f, double *x, long n, long b, double lambda, double theta) // Note change in function declaration
{
long i;
long j;
double u,v,y,z,w;
y = theta*lambda;
w = lambda*lambda;
z = 0.5*(theta+1.0)*w;
u = 0.0;
// n is the rows, b is the columns
for(i=0;i<n;i++)
{
for(j=0;j<b;j++) { // Added
v = fabs(x[j*n + i]); // Change here
if (v <= lambda)
u += lambda*v;
else if (v > y)
u += z;
else
u += 0.5*(v*(2*y - v) - w)/(theta-1.0);
} // Added
}
*f = u; // Change
//return; // Superfluous
}
您的 mexFunction
现在变为:
void mexFunction (int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
/*set up input arguments */
double *x = mxGetPr(prhs[0]); // Change
long n = (long)mxGetScalar(prhs[1]);
long b = (long)mxGetScalar(prhs[2]);
double lambda = mxGetScalar(prhs[3]);
double theta = mxGetScalar(prhs[4]);
int type = (int)mxGetScalar(prhs[5]);
double *f; // Change
/* set up output arguments */
plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);
f=mxGetPr(plhs[0]);
funcc(f, x, n, b, lambda, theta);
}
对于 hello2.c
,除了第二个 for
循环之外,一切都很好。您只需要用花括号将代码块括起来即可:
for(i=0;i<n;i++)
{
for(j=0;j<b;j++) { // added
u = fabs(d[j*n + i]);
xtemp[0] = min(lambda,max(0,u - lambda));
xtemp[1] = min(z,max(lambda,(u*(theta-1.0)-z)/(theta-2.0)));
xtemp[2] = max(z,u);
ytemp[0] = 0.5*(xtemp[0] - u)*(xtemp[0] - u) + lambda*xtemp[0];
ytemp[1] = 0.5*(xtemp[1] - u)*(xtemp[1] - u) + 0.5*(xtemp[1]*(-xtemp[1] + 2*z) - w)/(theta-1.0);
ytemp[2] = 0.5*(xtemp[2] - u)*(xtemp[2] - u) + 0.5*(theta+1.0)*w;
x[j*n + i] = xtemp[mymin(ytemp,3)];
x[j*n + i] = d[j*n + i]>= 0 ? x[j*n + i] : -x[j*n + i];
} //added
}
两个文件都需要额外的大括号,因为如果省略它们,C 只会将循环后的第一行视为循环体。 for
循环完成后的其余代码将被执行,而不是循环的一部分,这就是您出现段错误的原因。
关于从 MATLAB 调用 .c 文件会产生分段冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38484590/