MATLAB作為世界頂尖的數學應用軟件,以其強大的工程計算、算法研究、工程繪圖、應用程序開發、數據分析和動態仿真等功能,在航空航天、機械制造和工程建築等領域發揮著越來越重要的作用。而C語言功能豐富,使用靈活方便,目標程序效率高。既有高級語言的優點,又有低級語言的特點。因此,C語言是目前應用最廣的編程語言。雖然MATLAB是一個完整的、功能齊全的編程環境,但在某些情況下,與外部環境的數據和程序的交互是非常必須而且有益的。
眾所周知,MATLAB是用M語言編程,不能在M文件中直接調用C語言程序。可以通過MATLAB提供的應用編程接口(API)來實現與外部的接口,在MATLAB環境中實現調用C語言或Fortran程序、輸入或輸出數據以及和其他軟件程序間建立客戶/服務器關系等功能。
MATLAB中調用C語言程序,必須通過MEX文件來實現。
一、 C語言的MEX文件的結構
C語言的MEX文件是一種動態連接子程序,可以象調用M文件一樣調用它。MEX文件主要有以下幾方面的應用:
(1)在MATLAB中,M文件的計算速度特別是循環迭代的速度遠比C語言慢,因此可以把要求大量循環迭代的部分用C語言編寫為MEX文件,提高計算速度。
(2)已經開發的C語言程序,則不必將其轉化為M文件而重復勞動,通過添加入口程序mexFunction,可以由MATLAB調用。
(3)直接控制硬件,如A/D采集卡,D/A輸出卡等,以用於數據采集或控制應用。
C語言的MEX文件的源程序由兩個非常明顯部分組成:
(1)計算程序,即在MEX文件中完成計算功能的程序代碼,計算程序可以是普通的C語言程序,按照C語言規則編寫即可
(2)入口程序,將計算程序與MATLAB連接的入口函數mexFunction。入口程序mexFunction相對要復雜一些,函數中有四個參數nlhs、plhs、nrhs和prhs。這裡nlhs是輸出數據的個數,plhs是指向mxArray(MATLAB中所有數據都由mxArray定義)的輸出數據的指針,nrhs是輸入數據的個數,prhs是指向mxArray的輸入數據的指針。
圖1顯示了如何向MEX文件輸入數據,通過接口函數調用計算程序完成運算過程,最後向MATLAB返回計算結果的過程。
二、 使用MEX文件
上面所述的MEX文件的兩個主要部分在使用中可以是獨立的,也可以是組合在一起的。不管是哪一種情況,MEX文件都必須包含頭文件"mex.h",以便正常申明入口程序。入口程序的名字必須是mexFunction而且必須包含這些參數:
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在子程序執行前尚未產生,入口程序的作用就是創建輸出數組並分配指針plhs[0]指向該數組。如果plhs[0]沒有賦值,MATLAB將給出輸出變量沒有賦值的警告信息。
三、C語言程序MEX文件實例
MATLAB 5 API提供了一系列程序來處理MATLAB所支持的各種數據類型,每一種數據類型都有對應函數共你使用來處理對應的數據。下面給出一個簡單的C語言程序和與之對應的MEX文件代碼,該程序的功能是將標量x加倍。
C語言程序如下:
#include "math.h"
void timestwo(double y[], double x[])
{
y[0]=2.0*x[0];
return;
}
下面是與C語言程序功能相同的MEX文件:
#include "mex.h"
void timestwo(double y[], double x[])
{
y[0]=2.0*x[0];
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *x, *y;
int mrows, ncols;
/*檢查正確的參數數目*/
if(nrhs!=1){
mexErrMsgTxt("需要一個輸入參數.");
}
else if(nlhs>1){
mexErrMsgTxt("輸出參數太多.");
}
/*輸入變量必須是非復數類型的標量*/
mrows=mxGetM(prhs[0]);
ncols=mxGetN(prhs[0]);
if(!mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) || !(mrows==1 && ncols==1)){
mexErrMsgTxt("輸入變量必須是非復數類型的標量.");
}
/*為返回參數創建矩陣*/
plhs[0]=mxCreateDoubleMatrix(mrows, ncols, mxREAL);
/*分配輸入輸出參數的指針*/
x=mxGetPr(prhs[0]);
y=mxGetPr(plhs[0]);
/*調用timestwo子函數*/
timestwo(y, x);
}
C語言是在編譯的時候檢查函數參數。MATLAB可以在M函數中傳遞任意數量和類型的參數,MEX文件也是如此,不過在程序中必須可靠地處理輸入輸出參數的數目。如果將上面的MEX文件命名為timestwo.c,就可以對它進行編譯和鏈接,在MATLAB命令窗口下輸入:
mex timestwo.c
這是產生MEX文件timestwo.***所必需的步驟,該文件的擴展名所運行的系統平台的類型。Windows系統下,擴展名為dll。此時,就可以象調用M函數一樣調用timestwo了。
在MATLAB命令窗口中輸入:
x=2;
y=timestwo(x);
就可以得到:
y=4;
四、小 結
MEX文件雖然具有較強大的功能,但並不是對所有的應用都恰當。MATLAB是一個高效率的編程系統,特別適合於工程計算、系統仿真等應用。它的最大優點就是將人們從繁雜的程序中解放出來。因此,能夠用M文件完成的程序,應盡量使用MATLAB編寫,除非遇到必須使用MEX文件的情況。
MATLAB的應用編程接口是一個功能強大的系統,除了調用C或Fortran程序,還可以實現從MATLAB環境中輸入輸出數據、在MATLAB中和其他程序建立客戶/服務器關系等功能。