2015-11-02 155 views
2

我想從matlab中調用一個c函數,爲此我嘗試使用MEX編寫一個包裝函數。編譯時我得到 錯誤C2109:下標需要數組或指針類型 和錯誤C2440:'function':無法從'double *'轉換爲'double' 任何人都可以幫助我在哪裏做錯了?從MATLAB調用c函數?

#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; 
} 

回答

3

在你的主要功能,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就足以以列主要順序訪問單通道2D矩陣。如果您有多通道圖像,則只需要抵消height*width。該偏移允許您訪問其他通道中的圖像數據...並且由於您只有單通道數據(它看起來像......),因此不需要此偏移量。

因此,你只需要做:

outdata[r + height*c] = output[r][c]; 

如果你不這樣做,我懷疑你最終會得到分段錯誤,因爲你最終會訪問你不允許的內存部分訪問。


此外,一旦你完全測試你的代碼,擺脫mexPrintf語句。由於在嵌套的for循環中有它,因此它會不必要地將您的命令提示符填充爲打印消息。我懷疑你是否這樣做了調試,這很好,但是我建議你將MEX函數附加到實際的調試器上,並正確地調試代碼而不是打印語句。

查看我的帖子,瞭解如何在此處設置:Preventing a MEX file from crashing in MATLAB