轉]MATLAB 與 C 語言的接口

? ?MATLAB 到 C 語言程序的轉換可以由兩種途徑完成,其一是 MATLAB 自己提供的 C 語言翻譯程序 mcc, 另一種是原第 3 方公司 MathTools 開發的 MATCOM。后者出現較早,功能遠比 MATLAB 自己的翻譯程序強大,所以 MathTools 公司已經被 MathWorks 公司收購,并已將其開發技術融于新推出的 MATLAB 6.0 (Release 12) 中。?

??? 依本人的觀點,二者都不完善,有大量的 MATLAB 函數及數據類型是不能兼容變換的,所以有時會發現將簡潔的 MATLAB 程序翻譯成 C 語言程序很晦澀。翻譯后的 C 程序幾乎不適合手動去維護,更談不上升級了。?

??? 有幾個不兼容的地方是不能令人容忍的,例如 eval() 函數在 C 翻譯下是不兼容的,最新的 MATLAB 6 才剛剛敢說已經部分兼容了,但離真正的兼容還有很長的路要走,有很多艱難的技術困難需要克服,短時間內不可能有突破性的進展。另一個大的問題是,眾所周 知,MATLAB 新的控制系統工具箱中定義了大量的 LTI 類,MATLAB 5 開始也允許使用類與對象的概念,這已經向“面向對象”的編程走了一大步,但 MATLAB 到 C 的翻譯明顯都不支持“對象”的數據類型,所以在控制系統分析與設計 (當然還有其他的領域) 中這樣的轉換幾乎沒有什么實際意義,所以不要將這樣的轉換太理想化。?

??? 從轉換的程序速度來看,因為 mcc 和 MATCOM 都沿用了 MATLAB 的程序運算機制,所以不可能大幅度地提高程序運行速度。相反地,如果將 MATLAB 程序中明顯的瓶頸部分用 C 語言按照 MEX 格式編寫,則可以大大加快速度。作者在《科學運算語言 MATLAB 5.3 程序設計及應用》一書中以例子做過探討,MCC 可以比快 50%, 而 MEX 的形式可能快上百倍。?

〖舉例〗分形問題:從初始點(x0,y0) 出發,按下面的公式生成新的點 (x1,y1)?

其 中 gi 為 (0,1) 區間均勻分布的隨機數。要求從 (x1,y1) 再生成 (x2,y2),...,直至生成 1,000,000 個點(有點夸張,但太少了用 MATLAB 測時間不準)。可以下載用 MATLAB 的 M-函數寫的程序、用 Mex_C 寫的程序。程序調用語句為:?
??? >> N=1000000; v=rand(N,1); tic; [x,y]=frac_tree(0,0,v,N); toc?
?? 然后測試一下速度,再想法用 MATCOM 或 MCC 轉換一下,再試試速度。問題:MATCOM 程序到底比 M 函數快多少?我用 Mex_C 實現的速度可是快100多倍啊!下面有文章介紹,用 MATCOM+VC 能平均快1.5倍 (在別的應用上),依作者的觀點,為了這區區 1.5 倍還不至于自己給自己找麻煩去用 MATCOM。?

??? 這樣看,可能 MATLAB 到 C 轉換唯一的好處就是它能開發具有自主版權的軟件了。 所以本人一般不太贊同用這樣的轉換方法去開發程序,尤其不贊成刻意追求 MATLAB + C 的方式。本人認為:除非必要,一般別采用這樣的方法。提出這樣的觀點,歡迎商榷。?

??? MATCOM 目前有 BC 和 VC 兩個程序,MATLAB + VC 之家中收錄了一些文章。作者見到有下載區有這樣的軟件。?

在這里給出一個下載區的鏈接?
C++Builder 調用 Matlab 的實現方法?


國防科技大學機電工程與儀器系 張云洲?

摘要:本文簡要敘述了Matlab語言的優點,介紹了在用Borland C++Builder語言開發的Windows應用程序中,調用matlab語言實現科學計算和圖形繪制的方法。?

關鍵詞:C++Builder Matlab調用 混合編程?

1. 引言?

?? Matlab 是一個高度集成的系統,集科學計算、圖象處理、聲音處理于一體,具有極高的編程效率。近年來,Matlab已經從最初的“矩陣實驗室”,滲透到科學與工程 計算的多個領域,在自動控制、信號處理、神經網絡、模糊邏輯、小波分析等多個方向,都有著廣泛的應用。?

?? Borland C++Builder是一種新穎的可視化編程語言。在工程應用中,我們一般用C++Builder語言編寫應用程序,實現交互界面、數據采集和端口操作 等,但C++Builder在數值處理分析和算法工具等方面,其效率遠遠低于Matlab語言。在準確方便地繪制數據圖形方面,Matlab語言更具有無 可比擬的優勢。此外,Matlab還提供功能強大的工具箱。但Matlab的缺點是不能實現端口操作和實時控制。因此,若能將兩者結合運用,實現優勢互 補,將獲得極大的效益。?

?? 本文結合實際介紹了應用Borland C++Builder3.0開發的Windos應用程序中,對Matlab的調用方法。?

2. C++Builder調用Matlab的實現方案?

2.1 實現思路?

?? 在高版本的Maltab中(如Matlab V4.2)提供了DDE接口,用戶可以通過Windows的DDE通訊基制實現外部調用。這種實現方式比較簡單,但將增大主程序代碼,影響運行速度。?

?? 在Windows系統中,DLL是一種很特別的可執行文件,可以被多個Windows應用程序同時訪問,具有固定的共享數據段。該數據段的數據在DLL被 Windows下載前會一直保留在內存中,因此可以通過DLL實現用戶程序與Matlab之間的數據傳輸和函數調用。?

?? 具體地說, 就是利用Matlab的32位動態連接庫(DLL),生成相應的可以被C++Builder調用的DLL,用來提供二者之間的基本支撐環境。只需在用戶程 序中加載該DLL,即可實現其數據段的共享。然后在用戶程序中操作DLL數據段的數據,并通過某種方式在用戶程序中使Matlab執行該DLL,就可實現 用戶程序對Matlab的調用。其形式可以是混合編程或函數調用,非常方便而高效。?

2.2 實現方式?

?? Matlab提供了可外部連接的DLL文件,通過將其轉換為相應的Lib文件,并加以必要的設置,就可以在C++Builder中直接進行Matlab函數調用,實現C++ Builder語言與Matlab語言的混合編程。?

2.2.1 運行環境要求?

?? 由于Matlab提供的是32位的DLL。其運行環境要求是Matlab V4.2或更高版本。C++Builder可以進行32位編程,這里我們采用的是V3.0版本。?

2.2.2 C++Builder下LIB文件的生成?

?? Matlab提供的Def文件允許用戶通過Implib命令生成相應的Lib文件。其命令格式為:?

?? Implib ???.lib ???.def?

?? 在< matlab >\extern\include目錄下,提供了如下三個.Def文件:?

?? _libeng.def,_libmat.def,_libmx.def?

?? 通過上述命令可以生成相應的三個Lib文件。這些Lib文件中包含了可外部調用的Matlab函數的必要信息。?

3. C++Builder調用Matlab實現計算和繪圖?

?? 為清楚起見,作者通過一個簡單的CBuilder例程進行說明。該實例通過調用Matlab實現矩陣運算并繪制圖形,來演示C++Builder對 Matlab的調用。在C++Builder編輯環境中,建立一個新的窗體MyForm,并放置一個按鈕Demo。將工程文件命名為Try.prj,其主 函數為try.cpp。在主函數中,我們將使用一個實現Matlab調用的子函數DemoMatlab,作為按鈕Demo的響應事件。其源代碼如下:?

#i nclude < vcl.h >?
#pragma hdrstop?

#i nclude "Unit1.h"?
#pragma package(smart_init)?
#pragma resource "*.dfm"?
TMyForm *MyForm;?

__fastcall TMyForm::TMyForm(TComponent* Owner)?
: TForm(Owner)?
{?
}?

void __fastcall TMyForm::DemoClick(TObject *Sender)?
{?
DemoMatlab(); //演示Matlab語言調用?
}?
---- 為了調用Matlab中的函數,必須進行必要的設置,將包含這些函數的文件加入工程文件Try.prj。以下是操作過程:?

?? a. 在頭文件中加入Engine.h。其包含了啟動Matlab調用和關閉的函數聲明。?

?? b. 打開Project|Option…對話框,點擊Directories/Conditionals?

在Include Path中,加入目錄路徑< matlab >\extern\include,該路徑包含了engine.h和matlab.h等有用的頭文件。?

在Library Path中,加入< matlab >\bin和< matlab >\extern\include。這兩個目錄路徑包含了可外部調用的DLL和LIB文件。?
?? c. 點選Project|Add to Project…對話框,加入如下庫文件:?

?? _libeng.lib,_libmat.lib和_libmx.lib。?

?? 在進行了這些必要的設置之后,我們就可以選用適當的函數來實現目標。 以下是子函數DemoMatlab的程序代碼。?

???? void DemoMatlab?
{?
Engine *eng; //定義Matlab引擎?
char buffer[200]; //定義數據緩沖區?
int array[6]={1,2,3,4,5,6};?
mxArray *S = NULL, *T = NULL;?
engOpen(NULL); //打開MATLAB 引擎 ---①?

???? S= mxCreateDoubleMatrix(1,6, mxREAL);?
// 產生矩陣變量?
mxSetName(S, "S");?
???? memcpy((char *) mxGetPr(S),?
(char *) array, 6*sizeof(int));?
???? engPutArray(eng, S); //將變量X置入Matlab的工作空間?
engEvalString(eng, "T = S/S.^2;");?
//計算?
engEvalString(eng, "plot(S, T);");?
//繪制圖形?
…… ……?
engOutputBuffer(eng, buffer, 200);?
//獲取Matlab輸出?
???? T = engGetArray(eng, "T");?
//獲得計算結果----②?

???? engClose(eng);?
//關閉Matlab引擎,結束調用?
???? mxDestroyArray(S);?
//釋放變量?
???? mxDestroyArray(T);?
???? }?
?? 若還需要執行其它功能和任務,那么按照上面介紹的方法,進行變量聲明后,在①、②處加寫需要的語句既可。?

?? 當然,使用這種方法調用Matlab不能脫離Matlab環境的支撐。但當我們不需要看到Matlab的命令窗口時,可將其賦予Swhide屬性而加以隱藏。?

4. 結語?

?? 按照本文介紹的方法來實現C++Builder下應用程序對Matlab的調用,可以充分利用Matlab強大的科學計算功能和豐富的工具箱,而且具有混 合編程、方便高效的優點。這是C++語言和其它高級語言所無法比擬的。按照本文的方法,我們還可以編寫程序來最充分地利用Matlab的其它資源,開發滿 足自己需要的程序,更有效地完成我們的工作。?

VC++ 下如何利用 Matlab 工具箱進行數字信號處理?


潘 衛 明 趙 敏 張 進 芳?
(南京航空航天大學 測試工程系 210016)?

摘要:本文詳述了在Vc環境下如何利用Matlab工具箱進行數字信號處理,全文以Matlab工具箱中功率譜密度分析函數為例,介紹了通過Matlab自帶的引擎、Matlab自身的編譯器以及利用MathTools公司的Matcom進行對工具箱函數的調用。?

關鍵詞:Matlab M-文件 引擎 編譯器 Matcom Vc++?

?? Matlab 的信號處理工具箱是信號算法文件的集合,它處理的基本對象是信號與系統,信號處理工具箱位于目錄、Toolbox\Signal下,利用工具箱中的文件可 以實現信號的變換、濾波、譜估計、濾波器設計等。在其它的環境如Vc下如果能調用Matlab工具箱中的文件,會大大地加快一些算法的實現,同時其可靠性 也很高。?

利用Matlab引擎?
?? Matlab引擎采用客戶和服務器計算方式,在運用中,Vc的C語言或C++語言的程序 作為前端客戶機,它向Matlab引擎傳遞命令和數據信息,并從Matlab引擎接收數據信息,它提供了下列幾個函數: engOpen, engGetArray, engPutArray, engEvaString,?

engOutputBuffer ,engClose與客戶機進行交互。?

?? 下面例程是在Vc下建一個基于對話框的應用程序,在對話框中設置一個Button控件OnMatlabEngine.,在對話框 .cpp文件中加入”engine.h” 和“math.h” 頭文件,下面給出部分程序清單。?

Void CtestmatlabDlg::OnMatlabEngine(){?
Engine *ep;?
mxArray* T=NULL,*result=NULL,*mFs=NULL,*mnfft= NULL;?
double datax[1024];?
char buffer[1024];?
for(int j=0;j<1024;j++)//注:如通過采集卡采集數據可將采集的數據放在datax[]數組中,此循環就不需要?
{?
double samt=(double)(1.0/1024);?
datax[j]=sin(2.0*63.0*samt*3.1415926+1.15*3.1415926);?
}?
double *pPxx,*pFxx;?
if(!(ep=engOpen(" \0"))){//打開Matlab引擎,建立與本地Matlab的連接?
fprintf(stderr,"\n Can't start MATLAB engine\n");?
exit(-1);?
}?
double Fs[1]={1024};//因為Matlab所有參與運算的參數都是矩陣的形式,因而下列幾行將參數轉變?
double nfft[1]={1024};//成Matlab可接受的矩陣形式。?
T=mxCreateDoubleMatrix(1,1024,mxREAL);?
mnfft=mxCreateDoubleMatrix(1,1,mxREAL);?
mFs=mxCreateDoubleMatrix(1,1,mxREAL);?
mxSetName(T,"T");?
mxSetName(mnfft,"mnfft");?
mxSetName(mFs,"mFs");?
memcpy((char*)mxGetPr(T),(char*)datax, 1024*sizeof(double));?
memcpy((char*)mxGetPr(mnfft),(char*)nfft, sizeof(double));?
memcpy((char*)mxGetPr(mFs),(char*)Fs,1*sizeof(double));?
engPutArray(ep,T); //將轉化的參數放入引擎中,此時可在Matlab command窗口下查看此參數?
engPutArray(ep,mnfft);?
engPutArray(ep,mFs);?
engEvalString(ep,"[pxx,fo]=psd(T,mnfft,mFs);"); //利用引擎執行工具箱中文件?
engOutputBuffer(ep,buffer,512); //如只想看顯示圖形,可將返回參數去掉,psd無返回參數缺省情況下會自動畫圖形?
result=engGetArray(ep,"pxx");//取出引擎中的數據放在所指的區域中供后續處理?
pPxx=mxGetPr(result);?
result=engGetArray(ep,"fo");?
pFxx=mxGetPr(result);?
engEvalString(ep,"plot(fo,10*log10(pxx));");//利用引擎畫圖?
engEvalString(ep,"title('功率譜分析');");?
engEvalString(ep,"xlabel('Hz');");?
engEvalString(ep,"ylable('db');");?
mxDestroyArray(T); //釋放內存?
mxDestroyArray(mFs);?
mxDestroyArray(mnfft);?
mxDestroyArray(result);?
engEvalString(ep,"close;");?
engClose(ep);?
}?

?? 上述程序在Vc下編譯需要將 libeng.dll和libmx.dll兩個動態庫利用以下的命令:?

lib/def: <自己的Matlab的安裝路徑,下同>e:\ Matlab\extern\include\*.def /machine:ix86 /out:*.lib來生成程序所需的靜態連接庫libeng.lib和libmx.lib,將libeng.lib和libmx.lib所在的目錄加入 Vc++ project/link/object/library modules下即可。?

利用Matlab自身的編譯器調用工具箱中的函數?
?? Matlab 的編譯器可將Matlab的M文件轉換為為C或C++的源代碼以產生完全脫離Matlab運行環境的獨立的運用程序,但Matlab本身的資料說明編譯器 如用來建立獨立的運用程序,不能調用Matlab工具箱中的函數,這非常不利于搞一些特殊的算法。本人研究了一段時間發現,工具箱中的函數既然是M文件就 一定可以用編譯器來編譯,以提供如Vc的調用函數,但是編譯器只能編譯一個獨立的M文件,即這個 M文件不依賴于其他的M文件。如果M文件中又調用了其他的M文件,可將被調用的M文件拷貝到調用M文件的相應位置,作適當的改動就可以用于編譯器編譯。編 譯器不支持圖形函數,所以M文件中如有圖形函數需注釋掉。?

?? 當Matlab的編譯器mcc加入適當的參數-e(mcc –e *.*)或-p(mcc –p *.*)就可生成將輸入的M文件轉換為適用于特定運用的C或C++源代碼。這樣如果要在Vc下編譯通過,還需連入以下幾個庫libmmfile.dll,?libmatlb.dll, libmcc.dll, libmat.dll. libmx.dll. mibut.dll 以及Matlab C MATH庫,建議采用前述的方法將動態連接改為靜態連接。對于C/C++編譯環境的設置,在Matlab command窗口下運行mex –setup 然后依提示操作,而對于C/C++連接環境的設置,運行mbuild –setup依提示操作即可。?

?? 下面給出利用編譯器將Matlab工具箱中psd.m文件生成可供Vc調用的函數。?

將psd.m 文件拷貝一份至Matlab\bin目錄下,改寫相應調用的M文件如nargchk.m, hanning.m等。為生成的代碼簡潔,對于采集數據處理輸入參數很明了的情況下可作大量的刪減,最終使psd.m成為一個不依賴于其他M文件的獨立的 M文件,注意千萬注釋掉作圖代碼,最終改成如下形式,限于篇幅給出關鍵的幾步:?
function [Pxx,f]=psd(Fs,nfft,noverlap,x)?
window=o,5*(1-cos(2*pi*(1:nfft)’/(nffft+1)));//hanning 窗?
dflag=’none’;?
window=window(;)?
………………………………….?

以上只要稍懂Matlab語言和信號處理知識就可完成這項工作。?

假設上述代碼重新存為testwin.m,在Matlab command 窗口下設置好環境參數運行mcc –e testwin,則可在Matlab\bin下生成testwin.c ,如運行mcc –p testwin 則生成testwin.cpp.?
Vc下建立一個基于對話框的文件,然后在對話框里加一個Button控件OnButtonPsd?
將上述生成的.c文件的頭文件加入到工程的.cpp中,且將#ifdef_cplusplus?

extern “c”{?
#end if?
c代碼聲明加入Vc的包含文件和生成的.C的包含文件之間?
將#ifdef_cplusplus?
}?
#end if加入.cpp文件未尾?

為了簡潔且便于處理將生成的c函數稍改動,給出部分代碼如下:?

void CTestpsdwinDlg::OnButtonPsd(){?
mxArray* x_rhs_;//指向采集數據存放區?
Fs=23510;//數據采集的頻率 nfft=1024;//1024點的fft?
double datax[1024]//采集的數據?
x_rhs_mxCreateDoubleMatrix(1,1024,mxReal);?
memcpy(mxGetPr(x_rhs_),datax,1024*sizeof(double));?
noverlap=512;?
……………….?
……………….?
mccCopy(&Pxx,&Spec);?
mccCopy(&f,&frevgg_vector);?
for(int j=0;j<(int)(nfft/2+1);j++)?
{?
datap[j]=mccGetRealVectorElement(&Pxx, (j+1));//功率譜密度存于datap[]數組?
dataf[j]=mccGetRealVectorElement(&f, (j+1));//相應頻率存于數組dataf[]中?
}?
mccFreeMatrix(&Pxx);?
……………….?
SendMessageBox(WM_PAINT,0,0);//利用Vc下的圖形函數畫圖?
Return;?
}?

?? 如上生成的程序可讀性不太好,而生成的c++代碼則可讀性較好,但千萬注意只能用 Matlab的MATH庫,不可用c++的MATH庫,否則編譯會出錯,限于篇幅在此不述。?

3)利用Matcom調用工具箱中的函數?

?? Matcom 編譯M文件,先將M文件按照與Matcom的cpp庫的對應關系翻譯為cpp源代碼,然后用對應版本的c編譯器將cpp文件編譯成相應的exe或dll文 件,所以第一次運行要指定c編譯器的路徑,否則無法編譯,指定好的編譯信息就寫在Matcom\bin\matcom.ini文件中,不過這一步按裝 matcom時,它自動尋找編譯器并將其寫入matcom.ini文件中,matcom4.5版中使用TeeChart3.0 OCX控件,因而它支持圖形操作。 我們依然用上述的testwin.m文件,不要將圖形函數注釋掉,利用Mideva來生成可被Vc調用的信號處理程序。?

運行 Mideva在主界面上直打開M文件,在菜單中選擇compile to dll,輸入testwin..在Matcom debug目錄下可以找到這樣的幾個文件,testwin.c ,testwin.h,testwin.cpp,testwin.lib,testwin.dll,testwin.exp等。?
將上述testwin.cpp和testwin.h加入工程中,project/add to project/files并且在相應的文件中加入”stdafx.h”?
加連接庫:Tools\option\directory\ , 選include選項,加入e:\matcom45\lib (包含matcom.h)?
library選項,加入e:\matcom45\lib?

4) project\add to project\files 文件類型選項選(.lib)將e:\matcom45\lib\v4501.lib加入工程中編譯運行。相應代碼如下:?

void CtestmatcomDlg::OnpsdButton(){?
double datap[512],dataf[512];?
initM(MATCOM_VERSION);//初始化matcom庫?
Mm Fs,nfft,noverlap;//創建矩陣?
Mm x=zeros(1,1024);?
Fs=1024;nfft=1024;noverlap=128;?
dMm(Pxx_o);dMm(f_o);//創建并命名矩陣?
datax[];//數據采集的數據存于此數組中?
for(int i=1;i<=1024;i++)?
{?
x.r(1,i)=datax[i+1];//給x陣賦值?
}?
testwin(Fs,nfft,noverlap,x,i_o,Pxx,f_o);//matcom生成的函數?
for(i=0;i<513;i++){//取出功率譜密度分析結果?
dataf[i]=f_o.r(i+1,1);?
datap[i]=Pxx_o.r(i+1,1);}?
exitM();?
return;?
}?
?? 可見利用Matcom進行M文件轉換非常的容易,生成的代碼可讀性很好,以上的轉換同時生成了可供Vc調用的動態連接庫,其使用和一般的動態庫一樣使用。 同時需指明Matcom不僅可轉換獨立的不依賴于其它M文件的M文件,同時可轉換調用其它M文件的M文件嵌套。條件是這此M文件在同一個目錄下面,如前所 述的psd.m可直接用上述方法轉換,生成了多個重載形式的psd函數?

?? 結論: 利用Mtlab引擎調用工具箱中的函數可節省大量的系統資源,應用程序整體性能較好,但不可脫離Matlab 的環境運行。用Matlab編譯器進行工具箱函數的調用,須轉換相應的M文件使其成為獨立的M文件,且不支持圖形函數,轉換的代碼可讀性不太好。用 Matcom 進行轉換非常方便,生成的代碼可讀性很好,支持圖形函數,且代碼執行的速度比不轉換平均要快 1.5 倍以上。以上程序在Vc++ 6.0, Matlab 5.2, Matcom 4.5 中調試通過,以上方法在工程實踐中已得到很好的運用。?

通過 VC++ 實現對 MATLAB 的調用?


成都 .中國科學院光電技術研究所 郵編:610209 齊 波 董能力?

一 引言?

?? 眾所周知,MATLAB是功能非常強大的數學軟件,它廣泛應用于線性代數、自動控制理論、數理統計、數字信號處理、時間序列分析、動態系統仿真等領域。因 此如果把MATLAB的程序加入到自己的VC++、VB、POWER STATION及其它語言編制的程序中,將大大減少編程的工作量、保證程序的準確性,并且繼承VC++良好的用戶界面。下面就以VC++ 為例介紹一下它的外部調用。?

二 程序實現?

--作者實現外部調用的思路是:首先將m文件加入到一段C程序中,然后通過MATLAB中的mex批處理文件將該C文件生成exe文件,然后通過VC++的外部調用的函數:shellexec()或winexec()實現調用。 mex批處理文件的調用格式如下:?

mex -f msvc60engmatopts.bat *.c?
c文件的格式如下:?
/* engwindemo.c?
* This is a simple program that illustrates how to call the MATLAB?
* Engine functions from a C program for windows?
* Copyright (c) 1996-1998 by The MathWorks, Inc.?
* All Rights Reserved.*/?
#i nclude < windows.h >?
#i nclude < stdlib.h >?
#i nclude < stdio.h >?
#i nclude < string.h >?
#i nclude < d:\matlab\extern\include\engine.h >?
void main()?
{?
Engine *ep;?
/*?
* Start the MATLAB engine?
*/?
if (!(ep = engOpen(NULL))) {?
MessageBox ((HWND)NULL, (LPSTR)?
"Can't start MATLAB engine",?
?????????? , MB_OK);?
exit(-1);?
}?
???? engEvalString(ep, "contour(peaks)");?
?????? engClose(ep);?
}?

- 程序中的黑體部分即為要加入的m文件的位置。這樣就生成了與m文件同名的exe文件,通過VC++中的外部調用函數便很容易的實現了對MATLAB的調用。?
三 結 論?

本文給出了VC++等高級程序語言調用MATLAB中程序(函數)的方法,融合了VC++與MATLAB兩種不同的語言,大大提高了編程效率。不失為一種較好的程序設計方法。?

Matcom: Matlab 與 C++ 結合的有效途徑?


林 嵐* 周云波 楊玉星 林家瑞?
作者單位:華中理工大學生物工程系(武漢 430074)?
*男,24歲,碩士研究生?

摘 要 本文首先介紹了當前在國內外十分流行的工程設計和系統仿真軟件包Matlab的優缺點,然后展開介紹了Matcom(一種將Matlab與C++結合的工具)的功能及如何使用,最后對其效果進行了總結。   ?
關鍵詞 Matlab Visual C++ Matcom ECG?

1 工程設計軟件Matlab特點分析  ?

?? Matlab 是MathWorks公司于1982年推出的一套高性能的數值計算和可視化軟件。它集數值分析、矩陣運算、信號處理和圖形顯示于一體,構成了一個方便、界 面友好的用戶環境。它還包括了ToolBox(工具箱)的各類問題的求解工具,可用來求解特定學科的問題。其特點是:   ?

(1)可 擴展性:Matlab最重要的特點是易于擴展,它允許用戶自行建立指定功能的M文件。對于一個從事特定領域的工程師來說,不僅可利用Matlab所提供的 函數及基本工具箱函數,還可方便地構造出專用的函數,從而大大擴展了其應用范圍。當前支持Matlab的商用Toolbox(工具箱)有數百種之多。而由 個人開發的Toolbox則不可計數。
(2)易學易用性:Matlab不需要用戶有高深的數學知識和程序設計能力,不需要用戶深刻了解算法及編程技巧。?
(3) 高效性:Matlab語句功能十分強大,一條語句可完成十分復雜的任務。如fft語句可完成對指定數據的快速傅立葉變換,這相當于上百條C語言語句的功 能。它大大加快了工程技術人員從事軟件開發的效率。據MathWorks公司聲稱,Matlab軟件中所包含的Matlab源代碼相當于70萬行C代碼。   ?

?? 由于Matlab具有如此之多的特點,在歐美高等院校,Matlab已成為應用于線性代數、自動控制理論、數理統計、數字信 號處理、時間序列分析、動態系統仿真等高級課程的基本教學工具;在研究單位、工業部門,Matlab也被廣泛用于研究和解決各種工程問題。當前在全世界有 超過40萬工程師和科學家使用它來分析和解決問題。   ?

??? 然而Matlab自身所存在的某些缺點限制了它的應用范圍。?
(1) Matlab是一種解釋性語言,因此它的實時效率是相當差的。例如在筆者所從事的一個心電信號處理項目中,采用Matlab語言來處理5分鐘的心電數據, 在486/66系統機上需要25分鐘,而同樣的算法,用C語言實現,僅需30多秒。由此可見,Matlab的語言執行效率是比較低的。?
(2)Matlab程序不能脫離其環境運行,因此它不能被用于開發商用軟件。?
??? (3)Matlab程序可以被直接看到?

2 Matcom:Matlab與C++的完美結合?
MathTools公司推出的Matcom(可于http://www.mathtools.com處獲取)可以說是以上問題的完美解決。它可將Matlab的源代碼譯成同等功能的C++源碼。既保持了Matlab的優良算法,又保持了C++的高執行效率。?
下面將詳細介紹如何使Matlab與C++接口。?
運行環境:?
?????? Matcom 3.0?
?????? Matlab 5.1?
?????? Visual C++ 5.0?
?????? 中文Windows 95?
?????? PC:486/66   ?

?? (1)首先應設置Matcom所對應的編譯器類型、數據類型。?
?? (2)將你所需要的.M文件翻譯成C源碼。?

在這里將用一個簡單的濾波器Matlab源程序:?
Lin.m  ?

b=[1 2 1];   ?
a=[1 -1.58 0.64];n=50;   ?
x=[1, ones(1,n-1)];   ?
y=filter(b,a,x);   ?
plot(y./70,'*');   ?
hold on   ?
plot(x,'.');   ?
grid;  ?


下面給出了經Matcom翻譯后的C++源程序。Lin.cpp      ?

M b("b",0,0);   ?
M a("a",0,0);   ?
M n("n",0,0);   ?
M x("x",0,0);   ?
M y("y",0,0);   ?
b=(BR(1.0),2.0,1.0);   ?
a=(BR(1.0),-1.58,0.64);   ?
n=50.0;   ?
x=(BR(1.0),ones(1.0,n-1.0));   ?
y=filter(b,a,x);   ?
plot(rdivide(y,70.0),TM("*"));   ?
hold(TM("on"));   ?
plot(x,TM("."));   ?
grid();   ?

(3)Visual C++環境設置。   ?
在Visual C++中的"Project / Settings / C, C++ / Preprocessor /Additional include subdirectories" 中填入當前Matcom所處的路徑.。(如"c:\matcom\")在Visual C++中的工程窗口處" "Project / Add to Project / Files".加入mlibvc0.lib庫文件。   ?
(4)修改C++源代碼。  ?

注意:   ?
①在頭文件處應包含matlib.h.?

#define MLIB 0?
#i nclude "matlib.h."?

②在類成員函數CMfcApp::InitInstance中調用. InitM啟動對Matlab函數的調用。?

BOOL CEcgstarApp::InitInstance()  ?
??  {  ?
TRACE0("initM\n");?
initM(stin,stout,sterr);   ?
......?
}  ?

③在類構造函數CMfcApp::CMfcApp.中不要調用任何Matlab函數   ?
④在類構造函數CMfcApp::~CmfcApp中調用exitM結束對Matlab函數的調用。?

CEcgstarApp::~CEcgstarApp()   {     exitM();      }?

⑤在程序中合適的位置插入經Matcom翻譯過后的C++源碼。   ?
⑥編譯工程文件,就可得到你所需的結果。?

3 結束語  ?

?? 筆者在從事生物醫學工程ECG信號的檢測與處理項目中,對采用不同方法完成同一任務在代碼量和運行時間上進行了比較,如表1、表2所列。?

表1 ECG檢測核心算法代碼量?

全部用C++編寫 全部用Matlab編寫 用Matcom轉換后的C編寫?
約3400行 約400行 約600行?

表2 ECG檢測核心算法運行時間?

全部用C++編寫 全部用Matlab編寫 用Matcom轉換后的C編寫?
約30秒 約25分鐘 約1分鐘?

由此可見,采用Matcom進行程序設計,這是一種時間、效率上的極好的折衷,它使得你可以將更多的時間放在項目關鍵問題的思考上,而不是放在算法的實現和程序的編碼中,對于廣大工程技術人員的開發工作是十分有益的。?

Matlab 和 C++ 接口中函數注冊的實現?


李江紅 韓正之?
《計算機應用》COMPUTER APPLICATIONS 2000 Vol.20 No.4 P.18-20?

作者簡介:李江紅(1970-)男,湖南長沙人,博士研究生,主要研究方向:隨機決策以及智能控制;韓正之(1947-)男,上海人,教授,主要研究方向:非線性控制以及智能控制。?
作者單位:李江紅(上海交通大學智能工程研究所 上海 200030)?
韓正之(上海交通大學智能工程研究所 上海 200030)?

摘 要:函數注冊在Matlab和C++接口中起著重要的作用。在介紹函數注冊作用的基礎上,詳細分析了函數注冊的過程及應當注意的問題,并給出了一種實現函數注冊的最簡單的方法。用實例展示了函數注冊的具體實現過程。?
關鍵詞:Matlab;C++;函數注冊?
中圖分類號:TP317,TP319  文獻標識碼:A?
文章編號:1001-9081(2000)04-0018-03?

FUNCTION REGISTERING IN?
THE INTERFACE BETWEEN MATLAB AND C++?

LI Jiang-hong HAN Zheng-zhi?
(Intelligent Engineer Research Institute of Shanghai Jiaotong University, Shanghai 200030 China)?

Abstract: Function registration plays an important role in the interface between Matlab and C++. This paper analyzes the procedure of function registering. Each step of function registering is discussed in detail in the paper, and at the end,an example is given for illustration.?
Key words:Matlab; C++; function registration?


1 研究意義?

Matlab為用戶提供了豐富的Windows圖形界面設計方法,使用戶能夠在利用其強大數值計算功能的同時設計出友好的圖形界面。在編程效率、可讀 性、可移植性和可擴充性上,Matlab遠遠優于其它高級編程語言。Matlab能夠設計出功能強大、界面優美、性能穩定的高質量程序,它受到了越來越多 用戶的歡迎。然而作為一種以解釋方式運行的高級計算機語言,Matlab程序的執行效率較低。為了解決這一問題,MathWorks公司提供了 Matlab和C的接口。MathWorks公司提供的Matlab和C的接口方式共有三種:(a)將Matlab程序編譯成MEX文件C或C++文件; (b)在C,C++程序中利用Matlab Engine調用Matlab函數;(c) 在C,C++程序中利用Matlab C Math Library或Matlab C++ Math Library調用Matlab函數。其中通過方式(a)、(b)生成的程序只有在安裝了Matlab系統上才能正常運行,而由方式(c) 生成的程序則沒有這樣的要求,它能夠以獨立執行程序的形式運行,即使客戶沒有安裝Matlab系統。方式(c)唯一的缺點就是不能利用Matlab中豐富 的圖形句柄處理函數,但是對于VC++等開發工具而言,這不是一個很嚴重的問題。因此方式(c)是實現功能和效率兼顧的最好接口方法[2]。?

當用方式(c) 生成應用程序時,一個重要的問題就是那些以函數作為自身輸入參數的函數實現問題。眾所周知,Matlab提供了一組能完成極值及極值點計算,線性規劃,二次規劃以及非線性方程求解等數值運算的優化函數[3]。?

在Matlab中使用這組優化函數時,用戶定義的待優化函數必須作為輸入參數傳遞給這些函數。在優化函數運行的過程中,系統將最終執行用戶定義的待優化 函數,并且這一切無須程序員的參與。但是當程序員通過方式(c)在C++程序中調用Matlab C++ Math Library中的優化函數時,事情就變得比較復雜。要利用這些優化函數所提供的數值計算功能,保證用戶定義的待優化函數真正得到執行,程序員就必須自己 完成對待優化函數的注冊。因此,函數注冊的研究具有重要的實用價值。?

2 Matlab和C++接口中函數注冊?

在C++程序中,當調用優化函數等以函數為輸入參數的函數時,Matlab C++ Math Library調用Matlab C Math Library中的mlfFeval()來執行作為參數傳遞的函數。在mlfFeval()中又是通過對轉換函數的調用來真正地執行作為參數傳遞的函數。 轉換函數和映射表是這一過程能夠順利進行的重要原因。函數注冊就是定義函數的轉換函數并建立相應的它的映射表。對于Matlab C++ Math Library中的函數,MathWorks公司都定義了它們轉換函數并建立了它們的映射表,完成了對它們的注冊。但是對于用戶自定義的函數,程序員就必 須自己完成這項工作。?

函數注冊可以分成:(1)定義待注冊函數;(2)定義轉換函數;(3)建立映射表;(4)初始化映射表等以下四個部分來完成。下面將對各個部分進行詳細地介紹。?
(1) 定義待注冊函數 待注冊函數因用戶要求而異。為便于后面的分析,設用戶定義的函數為:?
mwArray MyFunc(mwArray x){?
……//函數體。?
}?
注意待注冊函數的輸入、輸出參數的類型必須是mwArray。mwArray是Matlab C++ Math Library中最基本的數據類,它對應Matlab中的基本編程單位—數組。?
(2) 定義轉換函數 轉換函數的功能是完成Matlab C Math Library和用戶函數之間的翻譯。由于它面向Matlab C Math Library,因此必須用C定義。對(1)中定義的待注冊函數,其轉換函數的一般形式如下(為簡單起見,該轉換函數忽略了錯誤處理代碼):?
typedef mwArray (*PMYFUNC) (mwArray);?
extern "C" {?
int MyThunk (mlfFuncp pFunc, int nArgOut, mxArray **?
ArgOut, int nArgIn, mxArray ** ArgIn){?
mwArray tmp=mwArray(ArgIn[0],0);?
mwArray Out=(*((PMYFUNC)pFunc)) (tmp);?
ArgOut[0]=Out.FreezeData( );?
return 1?
}?
}?
轉換函數共有5個輸入參數,以MyThunk為例,pFunc是指向待注冊函數的指針;nArgIn、nArgOut, 分別是待注冊函數的輸入、輸出參數的個數; ArgIn、ArgOut,則分別是輸入、輸出參數構成的數組。其中ArgIn[0]對應第1個輸入參數,ArgIn[1]對應第2個輸入參數……。 ArgOut的情形類似。?
由于轉換函數面向Matlab C Math Library,因此它的輸入、輸出參數中的數組類型只能是mxArray (mwArray是Matlab C Math Library中基本的數據,它對應Matlab中的基本編程單位—數組);而注冊的函數又只能接受mwArray類型的參數。因此,在調用注冊函數之前 必須將mxArray型數據轉化為mwArray型數據,如MyThunk中:mwArray tmp=mwArray(ArgIn[0],0); 在轉換函數返回之前必須將注冊的函數的返回值由mwArray型轉化為型mxArray,如MyThunk中:ArgOut[0]= Out.FreezeData()。?
(3) 建立映射表 映射表的作用是把待注冊函數的名稱映射到指向該函數的指針。映射表中的元素由三元組:函數名稱、函數指針、轉換函數構成。對(1)、(2)中定義的待注冊函數和轉換函數,相應的映射表為:?
static mlfFuncTabEnt MfuncTab[]={?
{"MyFunc", (mlfFuncp) MyFunc, MyThunk}?
{0, 0 ,0}?
}?
其中mlfFuncTabEnt是Matlab C Math Library中用于存儲函數項的數據結構。{0, 0 ,0}表示映射表的結束。?
(4) 初始化映射表 初始化映射表的方式比較單一。例如對(3)中的映射表,程序段:?
class feval—init{?
feval—init{mlfFevalTableSetup(MfuncTab);}?
static feval—init feval—setup;?
}?
feval—init feval—init::feval—setup;?
將完成其初始化。其中mlfFevalTableSetup是Matlab C Math Library中用于初始化映射表的函數。設置靜態對象的目的是保證映射表初始化在系統初始化靜態變量時就得以完成。?
從上面的分析可以看出,函數注冊的過程比較復雜。不過MathWorks公司注意到了這個問題,它定義并提供了DECLARE—FEVAL— TABLE, EVAL—ENTRY, END—FEVAL—TABLE等一組宏來幫助用戶簡單、輕松地完成函數注冊。例如對于(1)中定義的函數MyFunc,程序段:?
DECLARE—FEVAL—TABLE?
FEVAL—ENTRY(MyFunc)?
END—FEVAL—TABLE?
就實現了對MyFunc的注冊,它取代了(2)、(3)、(4)中的所有工作。事實上,只要待注冊函數的輸入參數數目不大于8,輸出參數數目不大于5,就能用這組宏來完成函數注冊。?

3 應用實例?

下面的VC++程序通過調用Matlab C++ Math Library中的fmin(),計算函數?
f(x,y)=ex(4x2+2y2+4xy+2y+1)?
在y=2時,位于區間[-2,2]中使函數值最小的自變量x的值。?
#i nclude "matlab.hpp"?
#i nclude <stdlib.h>?
/***(1) 定義注冊函數 ***/?
mwArray MyFunc(mwArray x,mwArray y){?
mwArray mResult=exp(x)*(4*x ^ 2+2*y ^ 2+4*x*y+2*y+1);?
return mResult;?
}?
/***(2) 定義轉換函數 ***/?
typedef mwArray (*PMYFUNC)(mwArray,mwArray);?
extern "C"{?
int MyThunk(mlfFuncp pFunc, int nArgOut, mxArray **?
ArgOut,int nArgIn, mxArray **ArgIn) {?
mwArray tmp1=mwArray( ArgIn[0], 0 );?
mwArray tmp2=mwArray( ArgIn[1], 0 );?
mwArray Out=(*((PMYFUNC)pFunc))(tmp1,tmp2);?
ArgOut[0]=Out.FreezeData();?
return 1;?
}?
}?
/***(3) 建立映射表 ***/?
static mlfFuncTabEnt MFuncTab[] ={?
{ "MyFunc", (mlfFuncp)MyFunc, MyThunk },?
{ 0, 0, 0 }?
};?
/***(4) 初始化映射表 ***/?
class feval—init {?
feval—init() { mlfFevalTableSetup( MFuncTab ); }?
static feval—init feval—setup;?
};?
feval—init feval—init::feval—setup;?
/***可以取代(2)(3)(4)的宏注冊函數 ****/?
/***  DECLARE—FEVAL—TABLE   ***/?
/***   FEVAL—ENTRY(MyFunc)  ***/?
/***  END—FEVAL—TABLE     ***/?
/*****    主程序      *****/?
void main(void){?
mwArray mStart,mEnd,mP,mOption;?
mStart=-2,mEnd=2;mP=2.0;?
mwArray mResult=fmin("MyFunc",mStart,mEnd,mOption,mP);?
cout < < mResult< < endl;?
}?

參考文獻?

[1] 薛定宇. 控制系統計算機輔助設計—MATLAB語言及應用[M].北京:清華大學出版社, 1996.17-19.?
[2] MATLAB C++ math Libarary User′s Guide[Z]. The Math Works, Inc., 1998.2-18.?
[3] 施陽,李俊.MATLAB語言工具箱—TOOLBOX實用指南[M].西安:西北工業大學出版社,1998.100-101.?

收稿日期:1999-10-19?

Matlab 與 C++ 混合編程?


??? Matlab 是當今世界上使用最為廣泛的數學軟件,它具有相當強大的數值計算、 數據處理、系統分析、圖形顯示,甚至符號運算功能,是一個完整的數學平臺,在這個平臺上,你只需寥寥數語就可以完成十分復雜的功能,大大提高了工程分析計 算的效率。另外由于Matlab的廣泛使用,于是出現了為各個領域專門使用的工具箱(即在某一研究領域常用數學工具的函數包),這些工具箱的出現更加促進 了Matlab的流行。?

?? Matlab強大的功能只能在它所提供的平臺上才能使用,也就是說,你必需在安裝有matlab系統的機 器上使用.m文件,這樣就給工程計算帶來了很大不便;特 別是,在matlab中,使用的行解釋方式執行代碼,這樣大大地限制了代碼執行速度。 于是人們想到,能否開發一個matlab與其他高級語言的接口,這樣就可以把matlab 的強大功能融入各種應用程序中,并且通過高級語言編譯器編譯為2進制代碼, 從而大大提高了執行速度。?

?? 于是matlab的5.1 版本提供了自帶的C++ Complier,同時MathTools公司也為 Matlab開發了m文件高效解釋和調試IDE:MIDEVA。經過近兩年的發展,matlab 5.3 中的C complier--mcc版本已經為2.0,而MIDEVA最新版本為4.5。?

?? 將matlab與C混合編程大概有如下三種方法:?

用Matlab的mcc將.m文件翻譯為cpp源文件,然后在C編譯器中調用 也可以用mcc編譯編譯為stand-alone程序。?

用Matcom(MIDEVA)將.m文件翻譯為cpp代碼,并編譯為exe或dll 文件。?

按照matcom的語法,在VC或BCB中直接書寫matlab語句(與matlab 很相似),這也是我最喜歡用的方法。?

?? 方法1和2/3各有利弊,1不支持圖形(支持圖形的庫國內現在還沒有D), 1對類支持也不夠,2支持絕大多數的matlab語句(包括圖形),但對于struct等的支持也有缺陷。?

??? MATLAB5.3 的提供了C/C++數學庫,其中的C++數學庫功能很強,使用它可以用類似MATLAB 的語法編寫C++程序,十分方便。雖然速度上仍然比手工C/C++程序慢,但是由此換來的高效的開發效率和可靠性往往是值得的。另外mcc命令可以將M文 件轉化為C或CPP文件,編譯后可以脫離MATLAB運行 ,它們也是使用的C/C++數學庫。 不過,MATLAB的數學庫在開發時似乎傾向于編譯獨立的可執行程序,把VC、BC只是作為一個編譯和連接的工具,而沒有過多地考慮在VC、BC的集成環 境下進行開發。這給我們帶來了不便。 很多網友問起如何將MCC生成的C++程序嵌入到VC。最近對這個問題做了一下嘗試,在這里做一個總結,請大家回去試試。這里只介紹VC的情況,用BC的 網友就自己研究研究吧估計是類似的。?

1、設置項目編譯選項 首先建立一個新的項目,或者打開一個已有的項目,然后選擇菜單?
Project->Settings->C/C++?
Category:Preprocessor?
Preprocessor definitions:?
添加: MSVC,IBMPC,MSWIND?
Category: Precompiled Headers?
選擇: Automatic use of precompiled headers?
Through header: stdafx.h?

2、調設置項目連接選項?
首先要從下面幾個函數定義文件(*.def)生成相應的導入庫文件(*.lib)?
libmmfile.def?
libmcc.def?
libmatlb.def?
libmx.def?
libmat.def?
它們位于目錄c:\matlab\extern\include?
用下面命令導出庫文件:?
lib /def:libmmfile.def /out:libmmfile.lib /machine:ix86?
lib /def:libmcc.def /out:libmcc.lib /machine:ix86?
lib /def:libmatlb.def /out:libmatlb.lib /machine:ix86?
lib /def:libmx.def /out:libmx.lib /machine:ix86?
lib /def:libmat.def /out:libmat.lib /machine:ix86?
將它們放入你的項目連接選項?
Project->Settings->Link?
Category:Input?
Object/library modules:?
添加:libmatpm.lib libmmfile.lib libmcc.lib libmatlb.lib libmx.lib libmat.lib?
注1: 中間是空格,不要加逗號?
注2: libmatpm.lib是C++ MathLib的庫,如果是只用C,就不用連接它了。?
Ignore libraries:?
添加: msvcrt.lib 注:?
僅在Debug版本中需要。原因不明.?

3、設置編譯環境?
Tools->Options->Directories?
Include fiels添加:?
c:\matlab\extern\include?
c:\matlab\extern\include\cpp?
Library fiels添加:?
c:\matlab\extern\lib?
c:\matlab\extern\include?
注:下面這個目錄是那些lib所在的地方。 如果都挪到上面的目錄,這個自然就不要了。?

4、編寫程序?
用MCC命令生成的CPP文件和自己手工編寫的CPP文件, 其項目設置是完全相同的, 程序的語法原則上也是一樣的. 只是MCC生成的CPP文件有大量"沒用"的代碼.?
(1)添加自己編寫的程序模塊?
用下面文件頭:?
#i nclude "stdafx.h"?
#i nclude "matlab.hpp"?
然后, 按照C++ MathLib文檔要求的格式書寫程序.?
(2)嵌入mcc生成的文件 在MATLAB下用下面格式的命令生成cpp文件 mcc -t -L Cpp test 得到test.hpp, test.cpp 將test.cpp加入項目, 不做任何改動. 最后,摁F7編譯就可以了。?

5、實例?
上面羅羅嗦嗦一大堆,肯定讓你打哈欠了:沒關系,其實還是挺簡單的,這里有個VC的project,用C++數學庫解決了一個幼兒園的算術題. 這里說明一下:?
MATLAB程序test.m:?
function [sum, prod]=test(x,y)?
sum = x+y;?
prod = x*y;?
用來計算兩個數的和與積。注意這是兩個返回變量的情況。 另外,x,y當然可以是數組。 用mcc命令生成了test.hpp和test.cpp。?
文件demo.cpp:?
#i nclude "stdafx.h"?
#i nclude "matlab.hpp"?
#i nclude "test.hpp"?
void mccDemo()?
{ CString str;?
mwArray x, y, sum, prod;?
double dx,dy,dsum,dprod;?
x = 5.0;?
y = 10.0;?
sum = test(&prod, x, y);?
dx=x(1,1);?
dy=y(1,1);?
dsum=sum(1,1);?
dprod=prod(1,1);?
str.Format("%f+%f=%f\n%f*%f=%f", dx,dy,dsum,dx,dy,dprod);?
AfxMessageBox(str); }?

?? 由于采用了C++數學庫,語法很簡單。注意數組的賦值、其中數據的存取,這些都要仔細地看手冊。 最后是跳出一個消息框,顯示計算結果。?

VC++ 中編譯 MEX 程序?


1. 目的?

?? 一般情況下,我們都是在MATLAB命令行或DOS命令行下編譯MEX程序。 所用的命令就是:mex filename.c 這有很多不方便的地方:?
?? a. 雖然mex也可以編譯C++的mex程序,但是它的主框架仍是C的 a. 當程序有多個模塊時,需要多次使用mex命令,操作很麻煩?
?? b. 不能利用VC特有的ClassWizard自動創建和維護類?
?? c. 不能用MFC類庫編寫應用程序?
?? d. 不能方便地進行類似VC的項目管理?
這樣一個命令行的編程環境可能會大大束縛你的想象力... 其實解決問題的方法很簡單,下面以VC6環境為例詳細解說如何在IDE中編譯MEX程序。?

2. 步驟?

(1)準備工作 (這里假設MATLAB的路徑為:C:\MATLAB)?
a. 由matlab.def創建庫文件matlab.lib?
進入c:\matlab\extern\include目錄,用lib命令生成matlib.lib?
?? C:\>cd \matlab\extern\include?
?? C:\MATLAB\extern\include>lib /def:matlab.def /out:matlab.lib?
?? Microsoft (R) Library Manager Version 6.00.8447?
?? Copyright (C) Microsoft Corp 1992-1998. All rights reserved.?
?? LIB : warning LNK4068: /MACHINE not specified; defaulting to IX86?
?? Creating library matlab.lib and object matlab.exp?
?? C:\MATLAB\extern\include>?
?? 警告信息不用理它。?
b. 修改mex.h?
該文件也在C:\MATLAB\extern\include目錄?
找到這一行:void mexFunction(?
替換為 : __declspec( dllexport ) void mexFunction(?
另保存為 :mex_vc.h?
(2)啟動VC,創建MFC AppWizard(dll)程序框架?
(3)設置系統選項?
a. 設定頭文件和庫文件路徑?
菜單Tools->Options->Directories?
Include files:添加c:\matlab\extern\include?
Library files:添加c:\matlab\extern\include?
b. 設置編譯連接選項?
菜單Project->Settings?
C/C++->Preprocessor definitions: 添加MATLAB_MEX_FILE?
Link->Object/Library modules: 添加matlab.lib?
注1. 其它優化、調試以及頭文件、庫文件等選項看情況調整?
注2. Release版在General->Microsoft Foundation Classes選項中, 必須設置為Use MFC in a Static Library. 原因不明 (4)編寫DLL主程序?
a. 文件名要用.cpp為擴展名,頭兩行必須是:?
#i nclude "stdafx.h"?
#i nclude "mex_vc.h"?
b. 編寫mexFunction函數,用如下格式聲明:?
void mexFunction(?
int nlhs, mxArray *plhs[],?
int nrhs, const mxArray *prhs[])?
{?
...?
}?
(5) 象普通VC的DLL程序一樣繼續編寫其它部分程序,加入其它模塊?
(6) 調試錯誤,用F7編譯,生成DLL。我的例子:?

--------------------Configuration: MatWave - Win32 Release--------------------?
Compiling resources...?
Compiling...?
StdAfx.cpp?
Compiling...?
MatWave.cpp?
sample.cpp?
mex.cpp?
Generating Code...?
Linking...?
Creating library Release/MatWave.lib and object Release/MatWave.exp?
LINK : warning LNK4089: all references to "SHELL32.dll" discarded by /OPT:REF?
LINK : warning LNK4089: all references to "comdlg32.dll" discarded by /OPT:REF?
MatWave.dll - 0 error(s), 2 warning(s)?

大功告成,有兩個警告,不理它。 拿到MATLAB里面試試吧,不過要有非法操作和異常退出的心理準備哦.?
另外:如果要在MATLAB運行中重新編譯DLL,需先執行: clear mex?

C++Builder與Matlab混合編程的實現?


長沙 張云洲?

在C++Builder中調用Matlab工具箱函數,有兩種實現方式。一種是基于Matlab環境支持,通過必要的設置實現;筆者在本刊上曾撰文對這種 方式進行了專門的闡述。另一種則是完全脫離Matlab環境,通過動態連接庫方式實現對Matlab工具箱函數的調用,這可以通過一種開發平臺 Mediva來實現。相對來說,前者的限制因素較多,而后者則較為方便靈活。?

一、Mediva軟件平臺?

Mediva是Mathtools公司推出的一種Matlab編譯開發軟件平臺,提供對Matlab程序文件(M文件)的解釋執行和開發環境支持。該軟件 有為Borland C++、Visual Basic和Dephi等編程語言開發的不同版本,目前其版本已經到了4.5版。軟件大小僅6.5M,可以通過訪問其站點 www.mathtools.com免費下載試用一個月。 Mediva軟件平臺本身的功能相當強大,提供近千個Matlab的基本功能函數,通過必要的設置,就可以直接實現與C++的混合編程,而不必再依賴 Matlab;同時,Mediva還提供編譯轉換功能,能夠將Matlab函數或編寫的Matlab程序轉換為C++形式的DLL,從而實現脫離 Matlab環境對Matlab函數和過程的有效調用,這樣就有可能實現對Matlab強大的工具箱函數的利用。?

Mediva的 缺點是C++與Matlab混合編寫的應用軟件必須攜帶必要的DLL,從而增大了軟件的體積(約4M),同時也不能對所有的Matlab函數提供支持,例 如采用類庫進行設計的部分函數。但盡管如此,對于控制系統計算機設計、分析的工作來說,Mediva仍不失為一個好的工具。?

由于利用Mediva將Matlab工具箱函數轉換成DLL的內容較多,限于篇幅本文在此僅給出對Matlab函數直接調用的實現,而將另撰文闡述DLL的實現。?

二、C++Builder直接調用Matlab函數?

本文假設已經安裝了Mediva軟件或已經得到必要的兩個動態連接庫mdv4300.dll和ago4300.dll。?

Mediva提供的近千個Matlab基本功能函數,都可以在C++Builder中直接調用。這些函數包括基本的操作、命令、I/O、線性代數、位 圖、控制等,基本上可以滿足我們的一般需要。當然其最大的優點就是可以直接在C++Buider中直接調用而不必考慮安裝龐大的Matlab。?

其實現方式和步驟如下:?

1.Lib文件的生成?

在Dos下用C++Builder中的Implib.exe,通過如下命令生成mdv4300.lib: implib mdv4300.lib mdv4300.dll?

將上述兩個DLL文件和此Lib文件拷貝到當前目錄下。?

2.實現與Matlab的混合編程?

Matlab.h包含了Mediva中所有類型、常量、函數的說明和定義,必須將此頭文件放于程序的第一行。Mediva給出的Matlab函數形式并 不特殊,如繪線函數Plot,在Mediva中說明為:Mm DLLI plot(cMm varargin);varargin與Matlab 中的意義是一樣的,與輸入變量的個數相對應。所有可以直接使用的函數都在Matlib.h頭文件中定義,而在mdv4300.dll中實現。?

但在C++Builder中使用Mediva提供的Matlab函數的格式,與Matlab編程稍有不同,這主要體現在C++中必須進行必要的說明上。 例如我們要用繪線函數Plot來繪制數組x[100]的紅色圖線。在Matlab中調用為Plot(x,'r');在C++中調用則為:Plot(CL (x),TM("r")),其中CL是一個關鍵字,是多變量輸入時所必須使用的,用以指明調用的變量;而TM則指明,這是一個字符。?

下面我們給出一個示例程序,其功能是對一個1024點的輸入數組進行FFT 變換,并繪制變換后頻譜實部的火柴桿圖,最后將原數據和變換后的數據寫入數據文件中。?

#i nclude "matlib.h"?
//必須包含的頭文件?
#i nclude < vcl.h >?
#pragma hdrstop?

#i nclude "TryMatcomU.h"?
#pragma package(smart_init)?
#pragma resource "*.dfm"?
TForm1 *Form1;?
__fastcall TForm1::TForm1(TComponent* Owner)?
???? : TForm(Owner)?
{?
}?
void __fastcall TForm1::Button1Click(TObject *Sender)?
{?
???? int k=0;?
???? initM(MATCOM_VERSION); //必須進行的初始化?
???? Mm cur1,cur2; //定義變量?
???? cur1=zeros(128); cur2=zeros(128); //變量初始化?

???? for (k=1;k< =128;k++)?
??? cur1.r(k)=randM(); //生成一個隨機數列?
???? figure(1);?
???? plot(cur1);//圖形顯示該數列?
?????
??? cur2=fft(cur1,128); //做128點fft變換?
??? figure(2);?
??? //繪制fft變換后實部的火柴桿圖,注意此處多變量輸入的格式?
??? stem((CL(cur1),real(cur2),TM("r")));?
????
fid=fopen(filename,mode,format) opens?
??? exitM(); //退出調用?
}?

如果完全使用C++來實現本程序的工作,其代碼將超過300行!由此可以看出,C++Builder與Matlab函數的混合編程可以給我們帶來多么大的方便!?
3.變量內部狀態/數據的觀察方法?

Mediva使用的所有變量均定義為Mm類型。如果在C++Builder中觀察Mm類型變量的內部狀態/數據,要稍麻煩一些。但在調試程序時,這又是不可避免的一步,這里舉例給出變量觀察的方法。?

例如對上面生成的cur2數列進行觀察,?
*cur2.pr 0.1892 cur2(1)的實部?
*cur2.pi 0.0013 cur2(1)的虛部?

三、C++Builder調用Matlab工具箱函數轉換后的DLL?

1.Matlab函數向DLL的轉化?

Mediva軟件提供了將Matlab函數轉換為DLL的功能,非常方便。但需要注意的是:?

1.Matlab5.0以上版本,所有帶有tf類的函數均無法轉換;?

2.Matlab4.2以下版本,多數函數能夠轉換,但轉換后大多不能直接使用,而必須加以處理。?

MATCOM V4.3中把含有輸入參數的M文件轉換成DLL時,生成的DLL無法調用.以.M為例,?

function [x1,x2]=flower(x3)?

MATCOM生成的FLOWER.CPP和FLOWER.H中聲明為:?

Mm flower(Mm x3, i_o_t, Mm& x1__o, Mm& x2__o) {?
begin_scope?
x3.setname("x3");?
...?
??? }?

Mm flower(Mm x3);?
Mm flower(Mm x3, i_o_t, Mm& x1__o, Mm& x2__o);?
而生成的G_FLOWER.CPP聲明為:?

---- void DLLX _stdcall flower_1_1(Mm** in01, Mm **out01)?

---- void DLLX _stdcall flower_1_2(Mm** in01, Mm **out01, Mm **out02)?

---- 其中對于in01的說明是不正確的.應按如下修改。然后,按如下MAKE文件進行編譯。?

#?
# MATCOM makefile?
#?

all: flower.dll?

g_flower.obj: g_flower.cpp?
bcc32 -c -Id:\matcom43\ -WD -Id:?
\matcom43\lib -H=matlib.csm -a4?
-5 -eg_flower.obj g_flower.cpp?

flower.dll: flower.obj g_flower.obj?
bcc32 -Ld:\matcom43\ -WD -Id:?
\matcom43\lib -H=matlib.csm -a4 -5 -eflower.dll?
@flower.rsp d:\matcom43\lib\mdv4300b.lib?

在CPP中調用這個函數之前,一定要先給in01分配空間。?
?? #i nclude "matlib.h"?
?? #pragma hdrstop?
???
?? #i nclude "flower.h"?
???
?? #define WIN32_LEAN_AND_MEAN?
?? #i nclude < windows.h >?
?? #i nclude "matlib.h"?
?? #pragma hdrstop?
???
?? extern "C" {?
???? void DLLX _stdcall flower_1_1(Mm in01, Mm **out01) {?
*out01=new Mm();?
//*in01=new Mm();?
**out01=flower(in01);?
exitM();?
???? }?
?????
???? void DLLX _stdcall flower_1_2(Mm in01, Mm **out01, Mm **out02) {?
*out01=new Mm(); *out02=new Mm();?
//*in01=new Mm();?
flower(in01, i_o , **out01, **out02);?
exitM();?
???? }?
?????

VC++調用MATLAB Engine?

實驗環境: Pwin98, MATLAB5.3, Visual C++ 6.0 SP3?
??? 1 生成幾個連接庫文件?
??? 在目錄 c:\matlab\extern\include 下找這幾個文件:?
??? libeng.def libmx.def libmat.def?
??? 在DOS行命令下生成三個庫文件:?
??? c:\msdev\bin\lib /def:libmat.def /out:libmat.lib?
??? c:\msdev\bin\lib /def:libeng.def /out:libeng.lib?
??? c:\msdev\bin\lib /def:libmx.def /out:libmx.lib?
??? 把生成的三個LIB文件加入你的LINK項?
??? libeng.lib libmx.lib libmat.lib?
??? 2 寫包含engine功能的文件?
??? 可以參考:?
??? c:\matlab\extern\examples\eng_mat\engwindemo.c?
??? 注意: 可以用.CPP做后綴. 比如:MATLAB.CPP?
??? 3 設置編譯選項?
??? 把MATLAB.C加入你的PROJECT?
??? MATLAB.C的開頭加入兩行:?
??? #i nclude "stdafx.h"?
??? #i nclude "engine.h"?
??? 包含其它頭文件, 自己看情況而定?
??? 4 編寫調用engine的函數?
??? 比如響應菜單調用自己的函數matlabPlot,而此函數的實現在matlab.cpp文件中實現,內容如下:?
??? #i nclude "stdafx.h"?
??? #i nclude "engine.h"?
??? int MatlabDraw()?
??? {?
??? Engine *ep;?
??? if (!(ep = engOpen(NULL))) {?
??? MessageBox ((HWND)NULL,"Can't start MATLAB engine","Matlab Draw",MB_OK);?
??? return 0;?
??? }?
??? engEvalString(ep, "x=0:0.01:2*pi;y=sin(x);plot(x,y);");?
??? engEvalString(ep, "title('Matlab Drawing');");?
??? engEvalString(ep, "xlabel('X');");?
??? engEvalString(ep, "ylabel('Y');");?
??? MessageBox(NULL, "Press any key …","MATLAB Draw",MB_OK);?
??? engClose(ep);?
??? return 1;?
??? }?
??? 5 設置其它編譯連接選項?
??? PreProcessor 加上: MATLAB_MEX_FILE?
??? INCLUDE 加上: c:\matlab\extern\include?
??? LIB 加上: c:\matlab\extern\include?
??? 最后,如果有必要的話,在DOS命令行運行: MATLAB /regserver

本文轉自博客園知識天地的博客,原文鏈接:轉]MATLAB 與 C 語言的接口,如需轉載請自行聯系原博主。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/279028.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/279028.shtml
英文地址,請注明出處:http://en.pswp.cn/news/279028.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

找call寫call_如何將Google Call Widget添加到任何網頁

找call寫callAdding a Google Call Widget to your website or blog allows visitors to contact you using your Google Voice number. The widget provides an easy and cost-effective way to provide live customer support without the customer knowing your real number…

XML與web開發-01- 在頁面顯示和 XML DOM 解析

前言&#xff1a; 關于 xml 特點和基礎知識&#xff0c;可以菜鳥教程進行學習&#xff1a;http://www.runoob.com/xml/xml-tutorial.html 本系列筆記&#xff0c;主要介紹 xml 在 web 開發時需要了解的知識 XML 在頁面顯示數據 XML 指可擴展標記語言&#xff08;eXtensible Mar…

酷安應用市場php源碼,酷安應用市場 v11.0.3-999 去廣告極限精簡版

酷安&#xff0c;真實有趣的數碼社區。酷安app&#xff0c;國內安卓應用市場客戶端&#xff0c;應用資源豐富&#xff0c;應用開發者水準高&#xff0c;應用無首發Logo&#xff0c;原汁原味上架&#xff0c;得到了安卓用戶群廣泛認可。有人說現在的酷安市場(酷安網)沒有以前那么…

再戰android-語音識別2(修改配置)

可怕的半桶水一直在晃。程序中需要根據用戶的選擇設置語音識別的語言&#xff08;目前科大訊飛支持英文、普通話、粵語&#xff09;&#xff0c;不想每次要用戶去IatSetting中去改&#xff0c;需要能直接修改IatSetting的設置。之前移植的IatSetting頁面沒有細究&#xff0c;直…

chromebook刷機_如何將網站添加到您的Chromebook架子上

chromebook刷機Bookmarks are great to keep your favorite sites nearby, but they aren’t the fastest option out there. Instead, why not add shortcuts for your favorite websites right on the Chromebook shelf? 書簽可以很好地將您喜歡的網站保留在附近&#xff0c…

php判斷外鏈,php檢查字符串中是否有外鏈的方法

這篇文章主要介紹了php檢查字符串中是否有外鏈的方法,涉及php針對字符串的正則匹配的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下本文實例講述了php檢查字符串中是否有外鏈的方法。分享給大家供大家參考。具體實現方法如下&#xff1a;/*** is_external_link 檢測字符…

【經驗分享】產品、運營人如何告別重復的數據分析工作?

我是一名互聯網的運營打雜MM&#xff0c;除了每天繁忙的工作&#xff0c;每周、每月的數據匯報也是我頭疼的東東。因為本身我不聰明&#xff0c;數學也不是太好&#xff0c;對數據不那么愛&#xff0c;而且還要做數據分析&#xff0c;對于我這種數據小白分分鐘崩潰。每周、每月…

JVM虛擬機調參

JVM虛擬機調參 一、堆大小設置JVM 中最大堆大小有三方面限制&#xff1a;相關操作系統的數據模型&#xff08;32-bt還是64-bit&#xff09;限制&#xff1b;系統的可用虛擬內存限制&#xff1b;系統的可用物理內存限制。32位系統下&#xff0c;一般限制在1.5G~2G&#xff1b;64…

Locktopus鎖定iOS設備上的單個應用程序

If you want to share a cool game on your iOS device but not let everyone read your email, Locktopus offers a simple app-by-app lockdown solution. 如果您想在iOS設備上共享一個很棒的游戲&#xff0c;但又不想讓所有人都閱讀您的電子郵件&#xff0c;那么Locktopus提…

php speedtest,大神教你如何搭建自己的web speedtest站點

導讀speedtest作為一款在線并且可視化的網速測試工具。使用方法簡單&#xff0c;無需下載、安裝多余軟件&#xff0c;只需有瀏覽器即可。那如何搭建一個自己的web speedtest站點呢&#xff1f;項目開源地址&#xff1a;https://github.com/adolfintel/speedtest安裝web,php,git…

MySQL服務器硬件和操作系統調節

1. 擁有足夠的物理內存來把整個InnoDB文件加載到內存中——在內存中訪問文件時的速度要比在硬盤中訪問時快的多。 2. 不惜一切代價避免使用Swap交換分區 – 交換時是從硬盤讀取的&#xff0c;它的速度很慢。 3. 使用電池供電的RAM&#xff08;注&#xff1a;RAM即隨機存儲器&am…

數據結構小結+模板

\[OI中的數據結構\] \[By\;TYQ\] 線性結構 大部略 單調棧 棧 , 但是push的時候要彈出所有比他小/大的(多用于優化Dp) 單調隊列 隊列 , 同單調棧 樹狀結構 樹狀數組 核心:lowbit(x) (x) & (-x) ...其實lowbit(x) 2^x的最低非0位 PION8012初賽中考了...但只涉及正數... 為什…

視頻翻錄_將DVD解密并復制到硬盤驅動器而無需翻錄

視頻翻錄Have you ever wanted to make backup copies of your DVDs but didn’t want to mess with confusing DVD ripping software? Today, we’ll look at drop dead simple method to decrypt DVDs on the fly with DVD43 so you can easily copy them to your hard dri…

詳解面向對象、構造函數、原型與原型鏈

詳解面向對象、構造函數、原型與原型鏈 為了幫助大家能夠更加直觀的學習和了解面向對象&#xff0c;我會用盡量簡單易懂的描述來展示面向對象的相關知識。并且也準備了一些實用的例子幫助大家更加快速的掌握面向對象的真諦。 jQuery的面向對象實現封裝拖拽簡易版運動框架封裝這…

如何將Wii遙控器用作陀螺儀鼠標

If you have a spare Nintendo Wii remote with the Motion Plus add-on, you can use it to control your Windows PC from across the room. Here’s how to get it working in a couple of easy steps. 如果您有帶Motion Plus附加組件的備用Nintendo Wii遙控器&#xff0c;則…

68.iOS設備尺寸及型號代碼(iPhoneXR/XS)

所有設備型號官網地址&#xff1a; https://www.theiphonewiki.com/wiki/Models iPhone: 機型像素比例像素密度屏幕尺寸機型代碼發布日期iPhone 2g4803203:2163ppi3.5iPhone1,12008.01iPhone 3g4803203:2163ppi3.5iPhone1,22008.06iPhone 3gs4803203:2163ppi3.5iPhone2,12009.0…

php 自帶 web server 如何重寫 rewrite .htaccess

為什么80%的碼農都做不了架構師&#xff1f;>>> <?php // filename: route.php if (preg_match(/\.(?:png|jpg|jpeg|gif|css|js)$/, $_SERVER["REQUEST_URI"])) {return false; } else {include __DIR__ . /index.php; } 更好的寫法&#xff1a; &l…

oracle11g導入錯誤,oracle 11g導入到10g引起的錯誤

環境介紹老環境新環境操作系統&#xff1a;redhat5.8 64位redhat6.4 64位數據庫版本&#xff1a;oracle 10.2.0.4 64位oracle 11.2.0.4 64位背景&#xff1a;之前有一套老的數據庫rac是基于oracle10g搭建&#xff0c;跑了幾年了。現在前端應用程序準備升級&#xff0c;考慮到前…

sci-hub谷歌插件_Google Home Hub具有隱藏屏幕設置菜單

sci-hub谷歌插件You can adjust the brightness or set an alarm on your Google Home Hub with a voice command. But if you’re trying to be quiet or there’s a lot of background noise, you can also do these things using a hidden Screen Settings menu. 您可以使用…

二叉樹的前序、中序、后序遍歷與創建

#include <iostream> #include <string> #include <stack> using namespace std; struct node; typedef node *pNode; struct node { char data; pNode left, right; }; string line; string::iterator it; // 前序擴展序列建立二叉樹 void plan…