⑴ 如何讓matlab用mex與C連接使用有例子 pdf
如果我有一個用C語言寫的函數,實現了一個功能,如一個簡單的函數:
double add(double x, double y)
{ return x + 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)。
值得注意的是,mex文件是與平台有關的,以我的理解,mex文件就是另類的動態鏈接庫。在matlab6.5中使用mex -v 選項,你可以看到最後mex階段有類似如下的信息:
--> "del _lib94902.obj"
--> "del "test.exp""
--> "del "test.lib""
也就是說,雖然在matlab6.5生成的是dll文件,但是中間確實有過lib文件生成。
比如該C文件已寫好,名為add.c。那麼在Matlab中,輸入:
>> mex add.c
就能把add.c編譯為MEX文件(編譯器的設置使用指令mex -setup),在Windows中,MEX文件類型為mexw32,即現在我們得出add.mexw32文件。現在,我們就可以像調用M函數那樣調用 MEX文件,如上面說到的例子。所以,通過MEX文件,使用C函數就和使用M函數是一樣的了。
我們現在來說mexFunction怎樣寫。
mexFunction的定義為:
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
}
可以看到,mexFunction是沒返回值的,它不是通過返回值把結果傳回Matlab的,而是通過對參數plhs的賦值。mexFunction的四個參數皆是說明Matlab調用MEX文件時的具體信息,如這樣調用函數時:
>> b = 1.1; c = 2.2;
>> a = add(b, c)
mexFunction四個參數的意思為:
nlhs = 1,說明調用語句左手面(lhs-left hand side)有一個變數,即a。
nrhs = 2,說明調用語句右手面(rhs-right hand side)有兩個自變數,即b和c。
plhs是一個數組,其內容為指針,該指針指向數據類型mxArray。因為現在左手面只有一個變數,即該數組只有一個指針,plhs[0]指向的結果會賦值給a。
prhs和plhs類似,因為右手面有兩個自變數,即該數組有兩個指針,prhs[0]指向了b,prhs[1]指向了c。要注意prhs是const的指針數組,即不能改變其指向內容。
因為Matlab最基本的單元為array,無論是什麼類型也好,如有double array、 cell array、 struct array……所以a,b,c都是array,b = 1.1便是一個1x1的double array。而在C語言中,Matlab的array使用mxArray類型來表示。所以就不難明白為什麼plhs和prhs都是指向mxArray類型的指針數組。
完整的add.c如下:
#include "mex.h" // 使用MEX文件必須包含的頭文件
// 執行具體工作的C函數
double add(double x, double y)
{
return x + y;
}
// MEX文件介面函數
void mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[])
{
double *a;
double b, 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函數的例子中,用戶輸入char array便是一種錯誤了。
從上面的講述中我們總結出,MEX文件實現了一種介面,把C語言中的計算結果適當地返回給Matlab罷了。當我們已經有用C編寫的大型程序時,大可不必在 Matlab里重寫,只寫個介面,做成MEX文件就成了。另外,在Matlab程序中的部份計算瓶頸(如循環),可通過MEX文件用C語言實現,以提高計算速度。
以上是對mex文件的初步認識,下面詳細介紹如何用c語言編寫mex文件:
1 為什麼要用C語言編寫MEX文件
MATLAB是矩陣語言,是為向量和矩陣操作設計的,一般來說,如果運算可以用向量或矩陣實現,其運算速度是非常快的。但若運算中涉及到大量的循環處理,MATLAB的速度的令人難以忍受的。解決方法之一為,當必須使用for循環時,把它寫為MEX文件,這樣不必在每次運行循環中的語句時MATLAB都對它們進行解釋。
2 編譯器的安裝與配置
要使用MATLAB編譯器,用戶計算機上應用事先安裝與MATLAB適配的以下任何一種ANSI C/C++編譯器:
5.0、6.0版的MicroSoft Visual C++(MSVC)
5.0、5.2、5.3、5.4、5.5版的Borland C++
LCC(由MATLAB自帶,只能用來產生MEX文件)
下面是安裝與配置MATLAB編譯器應用程序MEX的設置的步驟:
(1)在MATLAB命令窗口中運行mex –setup,出現下列提示:
Please choose your compiler for building external interface (MEX) files:
Would you like mex to locate installed compilers [y]/n?
(2)選擇y,MATLAB將自動搜索計算機上已安裝的外部編譯器的類型、版本及所在路徑,並列出來讓用戶選擇:
Select a compiler:
[1] Borland C++Builder version 6.0 in C:\Program Files\Borland
[2] Digital Visual Fortran version 6.0 in C:\Program Files\Microsoft Visual Studio
[3] Lcc C version 2.4 in D:\MATLAB6P5P1\sys\lcc
[4] Microsoft Visual C/C++ version 6.0 in C:\Program Files\Microsoft Visual Studio
[0] None
Compiler:
(3)選擇其中一種(在這里選擇了3),MATLAB讓用戶進行確認:
Please verify your choices:
Compiler: Lcc C 2.4
Location: D:\MATLAB6P5P1\sys\lcc
Are these correct?([y]/n):
(4)選擇y,結束MATLAB編譯器的配置。
3 一個簡單的MEX文件例子
【例1】用m文件建立一個1000×1000的Hilbert矩陣。
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
在matlab中新建一個Matlab_1.cpp 文件並輸入以下程序:
#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]);
hilb(y,n);
}
該程序是一個C語言程序,它也實現了建立Hilbert矩陣的功能。在MATLAB命令窗口輸入以下命令:mex Matlab_1.cpp,即可編譯成功。進入該文件夾,會發現多了兩個文件:Matlab_1.asv和Matlab_1.dll,其中Matlab_1.dll即是MEX文件。運行下面程序:
tic
a=Matlab_1(1000);
toc
elapsed_time =
0.0470
由上面看出,同樣功能的MEX文件比m文件快得多。
4 MEX文件的組成與參數
MEX文件的源代碼一般由兩部分組成:
(1)計算過程。該過程包含了MEX文件實現計算功能的代碼,是標準的C語言子程序。
(2)入口過程。該過程提供計算過程與MATLAB之間的介面,以入口函數mxFunction實現。在該過程中,通常所做的工作是檢測輸入、輸出參數個數和類型的正確性,然後利用mx-函數得到MATLAB傳遞過來的變數(比如矩陣的維數、向量的地址等),傳遞給計算過程。
MEX文件的計算過程和入口過程也可以合並在一起。但不管那種情況,都要包含#include "mex.h",以保證入口點和介面過程的正確聲明。注意,入口過程的名稱必須是mexFunction,並且包含四個參數,即:
void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
其中,參數nlhs和nrhs表示MATLAB在調用該MEX文件時等式左端和右端變數的個數,例如在MATLAB命令窗口中輸入以下命令:
[a,b,c]=Matlab_1(d,e,f,g)
則nlhs為3,nrhs為4。
MATLAB在調用MEX文件時,輸入和輸出參數保存在兩個mxArray*類型的指針數組中,分別為prhs[]和plhs[]。prhs[0]表示第一個輸入參數,prhs[1]表示第二個輸入參數,…,以此類推。如上例中,d→prhs[0],e→prhs[1],f→prhs[2],f→prhs[3]。同時注意,這些參數的類型都是mxArray *。
介面過程要把參數傳遞給計算過程,還需要從prhs中讀出矩陣的信息,這就要用到下面的mx-函數和mex-函數。
5 常用的mex-函數和mx-函數
在MATLAB6.5版本中,提供的mx-函數有106個,mex-函數有38個,下面我們僅介紹常用的函數。
5.1入口函數mexFunction
該函數是C MEX文件的入口函數,它的格式是固定的:
void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
說明:MATLAB函數的調用方式一般為:[a,b,c,…]=被調用函數名稱(d,e,f,…),nlhs保存了等號左端輸出參數的個數,指針數組plhs具體保存了等號左端各參數的地址,注意在plhs各元素針向的mxArray內存未分配,需在介面過程中分配內存;prhs保存了等號右端輸入參數的個數,指針數組prhs具體保存了等號右端各參數的地址,注意MATLAB在調用該MEX文件時,各輸入參數已存在,所以在介面過程中不需要再為這些參數分配內存。
⑵ 微信小程序里的pdf怎麼下載
可以下載的,需要通過後台第三方直接提取出PDF地址,就可以下載成PDF文件了