从 MATLAB 调用 c 函数?
calling c function from MATLAB?
我想从 matlab 调用一个 c 函数,为此我尝试使用 MEX 编写一个包装函数。在编译时我得到
error C2109: 下标需要数组或指针类型
和错误 C2440:'function':无法从 'double *' 转换为 'double'
任何人都可以帮助我在哪里做错了吗?
#include "mex.h"
#include "matrix.h"
#include "CVIPtoolkit.h"
#include "CVIPtools.h"
#include "CVIPmatrix.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void midd(double outdata, int type, int height, int width){
Image *outputImage;
byte **output;
int r,c;
mexPrintf("type %d\n", type);
mexPrintf("height %d\n", height);
mexPrintf("width %d\n", width);
outputImage=new_Image (PGM, GRAY_SCALE, 0, height, width, CVIP_BYTE, REAL );
outputImage = h_image(type, height,width);
output = getData_Image(outputImage, 0);
for(r=0; r < height; r++) {
for(c=0; c < width; c++)
{
mexPrintf("type %d\n", type);
mexPrintf("height %d\n", height);
mexPrintf("width %d\n", width);
outdata[r+height*c+height*width] =output[r][c]; /* passing data back to MATLAB variable from CVIPtools variable */
}
}
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *outdata;
int type, height, width;
// double *indata = (double *)mxGetData(prhs[0]);
type = mxGetScalar(prhs[0]);
height = mxGetScalar(prhs[1]);
width = mxGetScalar(prhs[2]);
mexPrintf("type %d\n", type);
mexPrintf("height %d\n", height);
mexPrintf("width %d\n", width);
plhs[0] = mxCreateDoubleMatrix(height,width,mxREAL);
outdata = mxGetData(plhs[0]);
midd(outdata, type, height, width);
}
我尝试调用的c函数如下:
#include "CVIPtoolkit.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
Image *
h_image(int type, unsigned int height, unsigned int width){
/* type = 1, Constant
* type = 2, Fixed mask
* type = 3, Gaussian
*/
unsigned int r, c, hf_w = width/2, hf_h = height/2;
Image *outimage;
float **outdata, sum = 0.0, sigma, tmp1, tmp2, tmp;
if (height < 3 || width < 3) {
fprintf(stderr, "Masksize too small, at least 3x3\n");
return (Image *)NULL;
}
outimage = new_Image(PGM, GRAY_SCALE, 1, height, width, CVIP_FLOAT, REAL);
outdata = (float **)getData_Image(outimage, 0);
switch (type) {
case 1:
for (r = 0; r < height; r++)
for (c = 0; c < width; c++) {
outdata[r][c] = 1.0;
sum += outdata[r][c];
}
break;
case 2:
for (r = 0; r < height; r++)
for (c = 0; c < width; c++) {
outdata[r][c] = 1.0;
sum += outdata[r][c];
}
outdata[height/2][width/2] = height * width;
sum = sum - 1.0 + outdata[height/2][width/2];
break;
case 3:
c = (width + height) /4;
r = (width + height) /2;
sigma = sqrt(c*c / (2 * log(2) + (r - 3) * log(3)));
sigma = 1.0 / 2.0 /sigma/sigma;
tmp = width * height;
for (r = 0; r < height; r++)
for (c = 0; c < width; c++) {
tmp1 = (r-hf_h)*(r-hf_h); tmp2 = (c-hf_w)*(c-hf_w);
outdata[r][c] = tmp*exp(- (tmp1 + tmp2) * sigma);
sum += outdata[r][c];
}
break;
default:
fprintf(stderr, "Incorrect mask type number: %d\n", type);
return (Image *)NULL;
}
return outimage;
}
在你的 main 函数中,outdata
是一个指向 double
的指针,而你的函数 midd
接受了一个实际的 double
本身。这就是为什么您会收到类型错误的原因。
只需更改您的函数声明,以便第一个输入接受指向 double
:
的指针
void midd(double *outdata, int type, int height, int width)
// ^^^^^^^^
小注
我质疑你将图像数据复制回 MEX 阵列:
outdata[r+height*c+height*width] =output[r][c];
您不需要 height*width
作为偏移量。 r + height*c
足以按列优先顺序访问单通道二维矩阵。如果你有一个多通道图像,你只需要偏移 height*width
。该偏移量允许您访问其他通道中的图像数据...并且由于您只有单通道数据(看起来如此...),因此不需要此偏移量。
因此,您只需要做:
outdata[r + height*c] = output[r][c];
如果不这样做,我怀疑您最终会遇到分段错误,因为您最终会访问不允许访问的内存部分。
此外,一旦您对代码进行了全面测试,请删除 mexPrintf
语句。它会不必要地用打印消息淹没您的命令提示符,因为您将它放在嵌套的 for
循环中。我怀疑您这样做是为了调试,这完全没问题,但我建议您将 MEX 函数附加到实际的调试器并正确调试您的代码,而不是打印语句。
请参阅我的 post,了解如何在此处进行设置:Preventing a MEX file from crashing in MATLAB
我想从 matlab 调用一个 c 函数,为此我尝试使用 MEX 编写一个包装函数。在编译时我得到 error C2109: 下标需要数组或指针类型 和错误 C2440:'function':无法从 'double *' 转换为 'double' 任何人都可以帮助我在哪里做错了吗?
#include "mex.h"
#include "matrix.h"
#include "CVIPtoolkit.h"
#include "CVIPtools.h"
#include "CVIPmatrix.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void midd(double outdata, int type, int height, int width){
Image *outputImage;
byte **output;
int r,c;
mexPrintf("type %d\n", type);
mexPrintf("height %d\n", height);
mexPrintf("width %d\n", width);
outputImage=new_Image (PGM, GRAY_SCALE, 0, height, width, CVIP_BYTE, REAL );
outputImage = h_image(type, height,width);
output = getData_Image(outputImage, 0);
for(r=0; r < height; r++) {
for(c=0; c < width; c++)
{
mexPrintf("type %d\n", type);
mexPrintf("height %d\n", height);
mexPrintf("width %d\n", width);
outdata[r+height*c+height*width] =output[r][c]; /* passing data back to MATLAB variable from CVIPtools variable */
}
}
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *outdata;
int type, height, width;
// double *indata = (double *)mxGetData(prhs[0]);
type = mxGetScalar(prhs[0]);
height = mxGetScalar(prhs[1]);
width = mxGetScalar(prhs[2]);
mexPrintf("type %d\n", type);
mexPrintf("height %d\n", height);
mexPrintf("width %d\n", width);
plhs[0] = mxCreateDoubleMatrix(height,width,mxREAL);
outdata = mxGetData(plhs[0]);
midd(outdata, type, height, width);
}
我尝试调用的c函数如下:
#include "CVIPtoolkit.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
Image *
h_image(int type, unsigned int height, unsigned int width){
/* type = 1, Constant
* type = 2, Fixed mask
* type = 3, Gaussian
*/
unsigned int r, c, hf_w = width/2, hf_h = height/2;
Image *outimage;
float **outdata, sum = 0.0, sigma, tmp1, tmp2, tmp;
if (height < 3 || width < 3) {
fprintf(stderr, "Masksize too small, at least 3x3\n");
return (Image *)NULL;
}
outimage = new_Image(PGM, GRAY_SCALE, 1, height, width, CVIP_FLOAT, REAL);
outdata = (float **)getData_Image(outimage, 0);
switch (type) {
case 1:
for (r = 0; r < height; r++)
for (c = 0; c < width; c++) {
outdata[r][c] = 1.0;
sum += outdata[r][c];
}
break;
case 2:
for (r = 0; r < height; r++)
for (c = 0; c < width; c++) {
outdata[r][c] = 1.0;
sum += outdata[r][c];
}
outdata[height/2][width/2] = height * width;
sum = sum - 1.0 + outdata[height/2][width/2];
break;
case 3:
c = (width + height) /4;
r = (width + height) /2;
sigma = sqrt(c*c / (2 * log(2) + (r - 3) * log(3)));
sigma = 1.0 / 2.0 /sigma/sigma;
tmp = width * height;
for (r = 0; r < height; r++)
for (c = 0; c < width; c++) {
tmp1 = (r-hf_h)*(r-hf_h); tmp2 = (c-hf_w)*(c-hf_w);
outdata[r][c] = tmp*exp(- (tmp1 + tmp2) * sigma);
sum += outdata[r][c];
}
break;
default:
fprintf(stderr, "Incorrect mask type number: %d\n", type);
return (Image *)NULL;
}
return outimage;
}
在你的 main 函数中,outdata
是一个指向 double
的指针,而你的函数 midd
接受了一个实际的 double
本身。这就是为什么您会收到类型错误的原因。
只需更改您的函数声明,以便第一个输入接受指向 double
:
void midd(double *outdata, int type, int height, int width)
// ^^^^^^^^
小注
我质疑你将图像数据复制回 MEX 阵列:
outdata[r+height*c+height*width] =output[r][c];
您不需要 height*width
作为偏移量。 r + height*c
足以按列优先顺序访问单通道二维矩阵。如果你有一个多通道图像,你只需要偏移 height*width
。该偏移量允许您访问其他通道中的图像数据...并且由于您只有单通道数据(看起来如此...),因此不需要此偏移量。
因此,您只需要做:
outdata[r + height*c] = output[r][c];
如果不这样做,我怀疑您最终会遇到分段错误,因为您最终会访问不允许访问的内存部分。
此外,一旦您对代码进行了全面测试,请删除 mexPrintf
语句。它会不必要地用打印消息淹没您的命令提示符,因为您将它放在嵌套的 for
循环中。我怀疑您这样做是为了调试,这完全没问题,但我建议您将 MEX 函数附加到实际的调试器并正确调试您的代码,而不是打印语句。
请参阅我的 post,了解如何在此处进行设置:Preventing a MEX file from crashing in MATLAB