摘要:在MATLAB中,M文件的計算速度特別是循環(huán)迭代的速度遠比C語言慢,因此可以把要求大量循環(huán)迭代的部分用C語言編寫為MEX文件,然后在MATLAB中調用此文件,以提高計算速度。該文通過實例詳述了如何實現此過程。
關鍵詞:MATLAB;C;MEX文件;接口
中圖分類號:TP312文獻標識碼:A文章編號:1009-3044(2009)24-7002-02
Implementation of Interface Between MATLAB and C Language Base on Mex File
LI Wei-gang
(Engineering College of Chinese People's Armed Police Force,Xi'an 710086,China)
Abstract: In MATLAB,the efficiency of M-file for caculation is down far from C language's when executing much iterative sentence.Therefore we may relize the part by compiled Mex-file by C language,then through calling the file on MATLAB to improve efficiency.The paper will set forth how to achieve the process by an example.
Key words: MATLAB; C; Mex-File; Interface
MATLAB作為世界頂尖的數學應用軟件,以其強大的工程計算、算法研究、工程繪圖、應用程序開發(fā)、數據分析和動態(tài)仿真等功能,在航空航天、機械制造和工程建筑等領域發(fā)揮著及其重要的作用。MATLAB是矩陣語言,是為向量和矩陣操作設計的,一般來說,如果運算可以用向量或矩陣實現,其運算速度是非常快的。但若運算中涉及到大量的循環(huán)迭代處理,MATLAB的速度的是令人難以忍受的[1]。解決方法之一為:當必須使用循環(huán)時,把它寫為MEX文件,這樣不必在每次運行循環(huán)中的語句時MATLAB都對它們進行解釋。而C語言功能豐富,使用靈活方便,目標程序效率高。因此,借助C語言來進行算法的設計,利用MATLAB完整的、功能齊全的編程環(huán)境來實現數據和程序的交互是非常必須而且有益的。
1 MEX文件的介紹
MEX文件是一種動態(tài)連接子程序,使用C語言和FORTRAN編寫,MATLAB對其格式做了統(tǒng)一規(guī)定,它是由MATLAB解釋器自動調用并執(zhí)行動態(tài)鏈接函數。在WINDOWS操作系統(tǒng)中這種文件類型的后綴名為dll。而其它平臺有較大變化[2],具體擴展名變化如表1所示。
2 C語言的MEX文件的組成與參數
C語言MEX文件的源程序由兩個不同的部分組成,每個部分完成不同的任務。
1) 計算子程序(Comutational Routine),它包含了實際完成計算功能的源代碼,用來完成實際的計算工作,它是以函數存在的,按照C語言規(guī)則編寫。
2) 入口子程序(Gateway Routine),它是計算子程序同MATLAB環(huán)境之間的接口,用來完成兩者之間的通信任務。是以入口函數mxFunction實現,通常所做的工作是檢測輸入、輸出參數個數和類型的正確性,然后利用mx-函數得到MATLAB傳遞過來的變量(比如矩陣的維數、向量的地址等),傳遞給計算子程序。
圖1顯示了如何向MEX文件輸入數據,通過接口函數調用計算程序完成運算過程,最后向MATLAB返回計算結果的過程。
MEX文件的兩個主要部分在使用中可以是獨立的,也可以是組合在一起的。但不管那種情況,都要包含#include \"mex.h\",以保證入口點和接口程序的正確聲明。注意,入口程序的名稱必須是mexFunction,并且包含四個參數[3],即:
void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
在C語言的MEX文件中,參數nlhs和nrhs包含輸出和輸入變量的數目,借助于這兩個參數,MEX文件被調用。參數plhs和prhs是包含指向MEX文件輸出和輸入變量的指針的向量,prhs是長度為nrhs的輸入變量的指針數組,plhs是長度為nlhs的輸出變量的指針數組。比如從MATLAB命令窗口來調用一個MEX文件:
x=fun(y,z);
則MATLAB編譯器使用下面的變量來調用mexFunction:
nlhs=1
nrhs=2
plhs=(pointer)->/*unassigned*/
prhs=(pointer)->y
(pointer)->z
plhs指向只有一個元素的C語言數組,并且這個元素為空指針。prhs指向含有兩個元素的C語言數組,其中第一個元素指向mxArray型變量y,第二個元素指向mxArray型變量z。這里,plhs指向空的數組是由于輸出x在子程序執(zhí)行前尚未產生,入口程序的作用就是創(chuàng)建輸出數組并分配指針plhs[0]指向該數組[4]。如果plhs[0]沒有賦值,MATLAB將給出輸出變量沒有賦值的警告信息。
3 MATLAB調用MEX文件實例
下面給出一個簡單的C語言程序和與之對應的MEX文件代碼,該程序的功能是建立一個1000×1000的Hilbert矩陣。
C語言程序如下:
#include \"math.h\"
void hilb(double *y,int n){
int i,j;
for(i=0;i for(j=0;j *(y+j+i*n)=1/((double)i+(double)j+1); } 下面是與C語言程序功能相同的MEX文件: #include \"mex.h\" //計算子程序 void hilb(double *y,int n){ int i,j; for(i=0;i for(j=0;j *(y+j+i*n)=1/((double)i+(double)j+1); } //接口子程序 void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]){ double x,*y; int n; if (nrhs!=1) mexErrMsgTxt(\"One inputs required.\"); if (nlhs != 1)/*檢查正確的參數數目*/ mexErrMsgTxt(\"One output required.\"); if (!mxIsDouble(prhs[0])||mxGetN(prhs[0])*mxGetM(prhs[0])!=1) mexErrMsgTxt(\"Input must be scalars.\"); x=mxGetScalar(prhs[0]); plhs[0]=mxCreateDoubleMatrix(x,x,mxREAL); n=mxGetM(plhs[0]); /*輸入變量必須是非復數類型的標量*/ y=mxGetPr(plhs[0]);/*分配輸入輸出參數的指針*/ if(!mxIsDouble(prhs[0]) mxIsComplex(prhs[0]) !(mrows==1 ncols==1)) mexErrMsgTxt(\"輸入變量必須是非復數類型的標量.\"); hilb(y,n); } C語言是在編譯的時候檢查函數參數,MATLAB可以在調用MEX文件時傳遞任意數量和類型的參數,但是在程序中必須可靠地處理輸入輸出參數的數目。如果將上面的MEX文件命名為Matlab_1.c,就可以對它進行編譯和鏈接,在MATLAB命令窗口輸入以下命令:mex Matlab_1.c即可編譯成功。進入該文件夾,會發(fā)現多了兩個文件:Matlab_1.asv和Matlab_1.dll,其中Matlab_1.dll即是MEX文件。 我們可比較MATLAB的M文件和調用MEX文件的執(zhí)行效率, 分別運行下面程序: tic m=1000; n=1000; a=zeros(m,n); for i=1:1000 for j=1:1000 a(i,j)=1/(i+j); end end toc elapsed_time = 0.1100 由上面看出,同樣功能的MEX文件比M文件快得多。 4 小結 MATLAB是一個高效率的編程系統(tǒng),特別適合于工程計算、系統(tǒng)仿真等應用。它的最大優(yōu)點就是將人們從繁雜的程序中解放出來。因此,能夠用M文件完成的程序,應盡量使用MATLAB編寫,但若是需要提高效率,我們又可借助MEX文件來實現,因為MATLAB系統(tǒng)外部程序調用接口的功能是相當強大的,通過它不但可以大量的縮短編程時間,并且使MATLAB的功能進一步增強。 參考文獻: [1] 劉志儉.Matlab 應用程序接口用戶指南[M].北京:科學出版社,2003. [2] 飛思科技產品研發(fā)中心.MATLAB7基礎與提高[M].北京:電子工業(yè)出版社,2006. [3] 儲開顏,嚴利民,王朔中.VC與MATLAB的接口及其實現[J].計算機工程,2000,26(12). [4] 郝紅偉.Matlab 6實例教程[M].北京:中國電力出版社,2003.