如何编写这个c文件的mexFunction
该函数是cyclic.c
。
void cyclic(float a[], float b[], float c[], float alpha, float beta, float r[], float x[], unsigned long n) // Solves for a vector x[1..n] the “cyclic” set of linear equations. a, //b, c, and r are input vectors, all dimensioned as [1..n], while alpha and beta are //the corner // entries in the matrix.
我是Matlab和C之间接口的新手。我已经好几年没用C了。 昨晚,我完成了它并编译。 最后一件事是打电话给它。
#include "mex.h" #include "nrutil.h" #define FREE_ARG char* #define NR_END 1 #include #include #include #define NR_END 1 #define FREE_ARG char* void nrerror(char error_text[]) /* Numerical Recipes standard error handler */ {fprintf(stderr,"Numerical Recipes run-time error...\n"); fprintf(stderr,"%s\n",error_text); fprintf(stderr,"...now exiting to system...\n"); exit(1); } float *vector(long nl, long nh) /* allocate a float vector with subscript range v[nl..nh] */ { float *v; v=(float *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(float))); if (!v) nrerror("allocation failure in vector()"); return v-nl+NR_END; } void free_vector(float *v, long nl, long nh) /* free a float vector allocated with vector() */ { free((FREE_ARG) (v+nl-NR_END)); } void tridag(float a[], float b[], float c[], float r[], float u[], unsigned long n) { unsigned long j; float bet,*gam; gam=vector(1,n); if (b[1] == 0.0) nrerror("Error 1 in tridag"); u[1]=r[1]/(bet=b[1]); for (j=2;j=1;j--) u[j] -= gam[j+1]*u[j+1]; free_vector(gam,1,n); } void cyclic(float a[], float b[], float c[], float alpha, float beta, float r[], float x[], unsigned long n) { void tridag(float a[], float b[], float c[], float r[], float u[], unsigned long n); unsigned long i; float fact,gamma,*bb,*u,*z; if (n <= 2) nrerror("n too small in cyclic"); bb=vector(1,n); u=vector(1,n); z=vector(1,n); gamma = -b[1]; //Avoid subtraction error in forming bb[1]. bb[1]=b[1]-gamma; //Set up the diagonal of the modified tridiagonal bb[n]=b[n]-alpha*beta/gamma; //system. for (i=2;i<n;i++) bb[i]=b[i]; tridag(a,bb,c,r,x,n);// Solve A · x = r. u[1]=gamma;// Set up the vector u. u[n]=alpha; for (i=2;i<n;i++) u[i]=0.0; tridag(a,bb,c,u,z,n);// Solve A · z = u. fact=(x[1]+beta*x[n]/gamma)/ //Form v · x/(1 + v · z). (1.0+z[1]+beta*z[n]/gamma); for (i=1;i<=n;i++) x[i] -= fact*z[i]; //Nowget the solution vector x. free_vector(z,1,n); free_vector(u,1,n); free_vector(bb,1,n); } void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { float *a,*b,*c,*x,*r; float alpha,beta; unsigned long n = (unsigned long) mxGetScalar(prhs[6]); // a=mxGetPr(prhs[0]); // b=mxGetPr(prhs[1]); // c=mxGetPr(prhs[2]); // r=mxGetPr(prhs[5]); a = (float*) mxGetData(prhs[0]); b = (float*) mxGetData(prhs[1]); c = (float*) mxGetData(prhs[2]); r = (float*) mxGetData(prhs[5]); // alpha=*(mxGetPr(prhs[3])); // beta=*(mxGetPr(prhs[4])); alpha = (float) mxGetScalar(prhs[3]); beta = (float) mxGetScalar(prhs[4]); plhs[0]= mxCreateDoubleMatrix(n, 1, mxREAL); x = mxGetPr(plhs[0]); mexPrintf("%f ",alpha); mexPrintf("\n"); mexPrintf("%f ",beta); mexPrintf("\n"); mexPrintf("%d ",n); mexPrintf("\n"); cyclic(a,b,c, alpha, beta,r,x,n) ; mexPrintf("%d ",n); mexPrintf("\n"); }
最后我成功地将它编译成cyclic(a,b,c, alpha, beta,r,x,n) ;
。 但答案是不对的。 我认为这是因为r
是一个虚构的向量。 所以我的问题是如何在C
和Matlab
之间转换r?
C函数cyclic
期望float
s的数组,但mexFunction
传递double*
。 在不更改cyclic.c
,您有两种选择:
-
在MATLAB中将数据转换为
single
数据,并使用mxGetData
获取float*
。在
mexFunction
:float *a = (float*) mxGetData(prhs[0]);
在MATLAB中:
mexFunction(single(a),...)
-
转换(复制,而不是
mexFunction
转换!)mexFunction
的数据。在
mexFunction
,分配新的float
数组,并将双输入数组(mxGetPr(prhs[0])
)中的每个元素复制到临时float
数组中。在MATLAB中使用普通的
double
数组调用mexFunction
。
做前者可能更容易。
在任何情况下你都不应该简单地使用指针,而不是你计划这样做。
此外,标量alpha
, beta
和n
需要从prhs
读取为标量并作为标量传递给cyclic
。 在mexFunction
,使用:
float alpha = (float) mxGetScalar(prhs[...]); float beta = (float) mxGetScalar(prhs[...]); unsigned long n = (unsigned long) mxGetScalar(prhs[...]);
你完全忘记了mexFunction
c
和r
。