首頁>Club>
10
回覆列表
  • 1 # 何以笙丶丶

    如果我有一個用C語言寫的函式,實現了一個功能,如一個簡單的函式:

    doubleadd(doublex,doubley){

    returnx+y;

    }

    現在我想要在Matlab中使用它,比如輸入:

    >>a=add(1.1,2.2)

    3.3000

    要得出以上的結果,那應該怎樣做呢?

    解決方法之一是要透過使用MEX檔案,MEX檔案使得呼叫C函式和呼叫Matlab的內建函式一樣方便。MEX檔案是由原C程式碼加上MEX檔案專用的介面函式後編譯而成的。

    可以這樣理解,MEX檔案實現了一種介面,它把在Matlab中呼叫函式時輸入的自變數透過特定的介面調入了C函式,得出的結果再透過該介面調回Matlab。該特定介面的操作,包含在mexFunction這個函式中,由使用者具體設定。

    所以現在我們要寫一個包含add和mexFunction的C檔案,Matlab呼叫函式,把函式中的自變數(如上例中的1.1和2.2)傳給mexFunction的一個引數,mexFunction把該值傳給add,把得出的結果傳回給mexFunction的另一個引數,Matlab透過該引數來給出在Matlab語句中呼叫函式時的輸出值(如上例中的a)。

    比如該C檔案已寫好,名為add.c。那麼在Matlab中,輸入:

    >>mexadd.c

    就能把add.c編譯為MEX檔案(編譯器的設定使用指令mex-setup),在Windows中,MEX檔案型別為mexw32,即現在我們得出add.mexw32檔案。現在,我們就可以像呼叫M函式那樣呼叫MEX檔案,如上面說到的例子。所以,透過MEX檔案,使用C函式就和使用M函式是一樣的了。

    我們現在來說mexFunction怎樣寫。

    mexFunction的定義為:

    voidmexFunction(

    intnlhs,

    mxArray*plhs[],

    intnrhs,

    constmxArray*prhs[]){

    }

    可以看到,mexFunction是沒返回值的,它不是透過返回值把結果傳回Matlab的,而是透過對引數plhs的賦值。mexFunction的四個引數皆是說明Matlab呼叫MEX檔案時的具體資訊,如這樣呼叫函式時:

    >>b=1.1;c=2.2;

    >>a=add(b,c)

    mexFunction四個引數的意思為:

    nlhs=1,說明呼叫語句左手面(lhs-lefthandside)有一個變數,即a。

    nrhs=2,說明呼叫語句右手面(rhs-righthandside)有兩個自變數,即b和c。

    plhs是一個數組,其內容為指標,該指標指向資料型別mxArray。因為現在左手面只有一個變數,即該陣列只有一個指標,plhs[0]指向的結果會賦值給a。

    prhs和plhs類似,因為右手面有兩個自變數,即該陣列有兩個指標,prhs[0]指向了b,prhs[1]指向了c。要注意prhs是const的指標陣列,即不能改變其指向內容。

    因為Matlab最基本的單元為array,無論是什麼型別也好,如有doublearray、cellarray、structarray……所以a,b,c都是array,b=1.1便是一個1x1的doublearray。而在C語言中,Matlab的array使用mxArray型別來表示。所以就不難明白為什麼plhs和prhs都是指向mxArray型別的指標陣列。

    完整的add.c如下:

    //add.c

    #include"mex.h"//使用MEX檔案必須包含的標頭檔案

    //執行具體工作的C函式

    doubleadd(doublex,doubley){

    returnx+y;

    }

    //MEX檔案介面函式

    voidmexFunction(

    intnlhs,

    mxArray*plhs[],

    intnrhs,

    constmxArray*prhs[]){

    double*a;

    doubleb,c;

    plhs[0]=mxCreateDoubleMatrix(1,1,mxREAL);

    a=mxGetPr(plhs[0]);

    b=*(mxGetPr(prhs[0]));

    c=*(mxGetPr(prhs[1]));

    *a=add(b,c);

    }

    mexFunction的內容是什麼意思呢?我們知道,如果這樣呼叫函式時:

    >>output=add(1.1,2.2);

    在未涉及具體的計算時,output的值是未知的,是未賦值的。所以在具體的程式中,我們建立一個1x1的實double矩陣(使用mxCreateDoubleMatrix函式,其返回指向剛建立的mxArray的指標),然後令plhs[0]指向它。接著令指標a指向plhs[0]所指向的mxArray的第一個元素(使用mxGetPr函式,返回指向mxArray的首元素的指標)。同樣地,我們把prhs[0]和prhs[1]所指向的元素(即1.1和2.2)取出來賦給b和c。於是我們可以把b和c作自變數傳給函式add,得出給果賦給指標a所指向的mxArray中的元素。因為a是指向plhs[0]所指向的mxArray的元素,所以最後作輸出時,plhs[0]所指向的mxArray賦值給output,則output便是已計算好的結果了。

    上面說的一大堆指向這指向那,什麼mxArray,初學者肯定都會被弄到頭暈眼花了。很抱歉,要搞清楚這些亂糟糟的關係,只有多看多練。

    實際上mexFunction是沒有這麼簡單的,我們要對使用者的輸入自變數的個數和型別進行測試,以確保

    輸入正確。如在add函式的例子中,使用者輸入chararray便是一種錯誤了。

    從上面的講述中我們總結出,MEX檔案實現了一種介面,把C語言中的計算結果適當地返回給Matlab罷了。當我們已經有用C編寫的大型程式時,大可不必在Matlab裡重寫,只寫個介面,做成MEX檔案就成了。另外,在Matlab程式中的部份計算瓶頸(如迴圈),可透過MEX檔案用C語言實現,以提高計算速度。

  • 中秋節和大豐收的關聯?
  • 那些在擂臺上打贏泰森的人,在街鬥中可以打得過他嗎?