周小娟
(西安外事學(xué)院 計(jì)算機(jī)中心,陜西 西安 710077)
Matlab是一款優(yōu)秀的,功能強(qiáng)大的科學(xué)計(jì)算軟件,它為航空航天,控制,機(jī)械,電子,電力,生物,財(cái)務(wù)等眾多領(lǐng)域提供功能強(qiáng)大的數(shù)值計(jì)算和仿真工具。Matlab環(huán)境下的M語(yǔ)音,簡(jiǎn)單靈活,使用方便,但做為一種編程語(yǔ)言,在圖形界面開發(fā)方面和Java,C++等高級(jí)語(yǔ)音相比卻顯得不夠強(qiáng)大。Matlab雖然提供了一些圖形開發(fā)功能,并且利用這些功能開發(fā)相對(duì)簡(jiǎn)單的圖形界面也很受歡迎,但對(duì)于稍微復(fù)雜一些的圖形界面和大型專業(yè)的軟件產(chǎn)品,這些功能就無(wú)法實(shí)現(xiàn)了。因此在大型專業(yè)軟件產(chǎn)品開發(fā)中,必須研究一種新的開發(fā)方法,將Java,C++等高級(jí)語(yǔ)言的圖形界面開發(fā)優(yōu)勢(shì)和Matlab數(shù)據(jù)計(jì)算和仿真的優(yōu)勢(shì)結(jié)合起來(lái),開發(fā)更為專業(yè)的軟件產(chǎn)品。幸運(yùn)的是,Matlab已經(jīng)提供了和Java,C,C++等高級(jí)開發(fā)語(yǔ)言的接口,因此將Matlab程序整合進(jìn)Java,C,C++程序是可行的。
Matlab提供將M程序編譯為C/C++動(dòng)態(tài)庫(kù)或者Java包的功能。 在Deployment Tool中用戶可以選擇要編譯的M文件以及編譯結(jié)果的類型,然后Deployment Tool將調(diào)用編譯器mcc(MATLAB COMPILER COMMAND)對(duì)目標(biāo)文件進(jìn)行編譯。mcc具有將M文件編譯為C/C++動(dòng)態(tài)庫(kù),Java包,可執(zhí)行文件的能力,是Matlab和其它語(yǔ)言混合編程中必須使用的一個(gè)工具。Matlab還提供另外一個(gè)工具mbuild將C/C++程序編譯為可執(zhí)行文件或者動(dòng)態(tài)庫(kù),mbuild內(nèi)部將調(diào)用操作系統(tǒng)已經(jīng)安裝的編譯器進(jìn)行編譯。
Java語(yǔ)言具有優(yōu)秀的圖形界面開發(fā)能力,常用的圖形開發(fā)庫(kù)有基于 AWT(Abstract Window Toolkit)的 Java-Swing 開發(fā)技術(shù)和基于 SWT(Standard Widget Toolkit)的 Eclipse開發(fā)技術(shù)。AWT具有和Java類似的和操作系統(tǒng)無(wú)關(guān)的特征,因此在Windows上開發(fā)的AWT程序,在Linux上運(yùn)行具有相同的界面風(fēng)格。SWT使用操作系統(tǒng)提供的圖形界面,和程序運(yùn)行的操作系統(tǒng)具有直接關(guān)系,因此在Windows上開發(fā)的SWT程序,具有Windows操作系統(tǒng)的風(fēng)格,在Linux上運(yùn)行時(shí)具有Linux操作系統(tǒng)的風(fēng)格。因?yàn)镾WT直接調(diào)用的是操作系統(tǒng)本身的圖形庫(kù),因此SWT可以提供完全的圖形界面,功能比AWT要強(qiáng)大的多。本文將使用SWT在W indowsXP操作系統(tǒng)上進(jìn)行Java程序圖形界面的開發(fā)。
在Java中調(diào)用Matlab程序有兩種方法:1.將Matlab程序編譯為Java包,然后在Java程序中調(diào)用Java包中的類和方法;2.將Matlab程序編譯為C/C++動(dòng)態(tài)庫(kù),然后通過(guò)JNI(Java Native Interface)在Java程序中調(diào)用。第一種方法的實(shí)施比較簡(jiǎn)單,直接在Matlab中調(diào)用Deployment Tool就可以完成;第二種方法的實(shí)施比較復(fù)雜一些,需要編寫Java Native類和C/C++代碼,但在執(zhí)行效率方面具有優(yōu)勢(shì)。因此在這兩種方法的選擇上以程序的規(guī)模和效率為參考進(jìn)行,如果Matlab程序的規(guī)模比較小,處理的數(shù)據(jù)量比較小,可以選擇第一種方法,反之選擇第二種方法。對(duì)于執(zhí)行效率比較重要的程序來(lái)說(shuō),可以用兩種方法來(lái)實(shí)現(xiàn)混合編程,然后通過(guò)對(duì)比選擇效率高的一種方法進(jìn)行實(shí)施。下面對(duì)這兩種方法的實(shí)現(xiàn)過(guò)程分別進(jìn)行描述。
將Matlab程序編譯為Java包,然后在Java程序中調(diào)用Java包中的類和方法,這種混合編程方法相對(duì)比較簡(jiǎn)單。具體步驟如下:
1)在Matlab命令行輸入deploytool啟動(dòng)Deployment Project對(duì)話框。
2)在對(duì)話框中輸入編譯項(xiàng)目名稱及其位置,并選擇Java Package為編譯類型。
圖1 創(chuàng)建編譯項(xiàng)目Fig.1 Create a deployment project
3)在Java Package頁(yè)面中,通過(guò)添加類為要生成的Java類命名,然后通過(guò)添加文件為這個(gè)類添加相關(guān)的M文件。
圖2 為編譯項(xiàng)目命名要?jiǎng)?chuàng)建的Java類并添加M文件Fig.2 Add Java class and M files for the deployment project
4)點(diǎn)擊Java Package頁(yè)面右上方的Build按鈕進(jìn)行編譯。
編譯完成后,在編譯項(xiàng)目所在目錄將生成一個(gè)以編譯項(xiàng)目名稱命名的目錄,在這個(gè)目錄內(nèi)有兩個(gè)子目錄distrib和src。distrib子目錄放置編譯好的Java包和幫助文檔,這些都是我們期望的結(jié)果,其中Java包就是混合編程中Java一方需要用到的唯一文件。src子目錄內(nèi)放置的是Java包中類的代碼文件,這些文件是中間產(chǎn)物,混合編程中Java一方不需要這些文件。因此一般不需要關(guān)心src子目錄中的產(chǎn)物。
混合編程中在Matlab一方編譯生成Java包后,Matlab的編程任務(wù)就完成了。下面需要在混合編程中Java一方調(diào)用該Java包中的類和方法。具體的調(diào)用方法如下,
1)將Matlab生成的Java包包含在Java項(xiàng)目的classpath中。這就保證了Java包中的類在當(dāng)前Java項(xiàng)目?jī)?nèi)可以訪問到;
2)在調(diào)用Matlab算法的Java類文件中導(dǎo)入com.mathworks.toolbox.javabuilder.*和MATLAB編譯生成的Java類;
import com.mathworks.toolbox.javabuilder.*;
import rankine_package.*;
3)在調(diào)用Matlab算法的Java類文件就可以直接使用MATLAB編譯生成的類了;
rankineClass MLRankine=new rankineClass();
Object[]Output=MLRankine.rankine(1, Input);
這個(gè)例子中,rankineClass就是在Matlab中編譯生成的Java類,其方法rankine()就是M文件rankine.m中實(shí)現(xiàn)的Matlab算法,第一個(gè)參數(shù)的值1表示這個(gè)算法的返回值只有一個(gè)。
將Matlab程序編譯為C/C++動(dòng)態(tài)庫(kù),然后在C/C++程序中調(diào)用該動(dòng)態(tài)庫(kù)生成另外一個(gè)動(dòng)態(tài)庫(kù),最后通過(guò)JNI(Java Native Interface)在Java程序中調(diào)用Matlab程序中的函數(shù)對(duì)應(yīng)的C/C++函數(shù),這種混合編程方法相對(duì)比較復(fù)雜。具體步驟如下:
1)首先必須選擇并設(shè)置Matlab中mcc和mbuild在編譯時(shí)使用的C/C++編譯器。通過(guò)在Matlab中輸入 “mbuild–setup”,Matlab會(huì)把當(dāng)前操作系統(tǒng)已經(jīng)安裝的C/C++編譯器列出來(lái),這時(shí)候只需要選擇要使用的一個(gè)編譯器就可以了。如果當(dāng)前系統(tǒng)沒有安裝任何編譯器,需要安裝一個(gè)。在Linux操作系統(tǒng)上,可以安裝gcc。在Windows操作系統(tǒng)上,可以安裝Microsoft Visual Studio for C/C++。
2)在設(shè)置好編譯器后,就可以啟動(dòng)deployment tool將要使用的M文件編譯為C/C++動(dòng)態(tài)庫(kù)了。編譯過(guò)程和2.1節(jié)一樣,只不過(guò)編譯類型需要選擇C動(dòng)態(tài)庫(kù),或者C++動(dòng)態(tài)庫(kù)。編譯結(jié)果中distrib目錄中有4個(gè)結(jié)果文件在后續(xù)的步驟中要用到:一個(gè)*.dll文件,這是編譯的結(jié)果動(dòng)態(tài)庫(kù)包含MATLAB程序?qū)?yīng)的函數(shù);一個(gè)*.h文件,動(dòng)態(tài)庫(kù)中函數(shù)的列表,在調(diào)用動(dòng)態(tài)庫(kù)的程序中需要用到;一個(gè)*.lib文件,動(dòng)態(tài)庫(kù)對(duì)應(yīng)的靜態(tài)庫(kù);一個(gè)*.exports文件,羅列了所有*.h中的函數(shù)名稱。在*.h文件中,每一個(gè)Matlab程序的函數(shù)都有一個(gè)對(duì)應(yīng)的C/C++函數(shù),除此之外,還有兩個(gè)函數(shù)也必須被用到,它們是xxxInitialize()和 xxxTerminate(),其中 xxx 是編譯項(xiàng)目的名稱。xxxInitialize()必須在調(diào)用任何Matlab函數(shù)對(duì)應(yīng)的C/C++函數(shù)之前調(diào)用,xxxTerminate()必須在所有調(diào)用完成后,程序結(jié)束前調(diào)用。
3)在編譯完 Matlab程序后,就可以進(jìn)行 JNI(Java Native Interface)程序的開發(fā)了,通過(guò)JNI程序?qū)崿F(xiàn)在Java圖形界面程序中調(diào)用C/C++動(dòng)態(tài)庫(kù)。
①首先必須在Java圖形界面程序中聲明一個(gè)Java類包含若干native方法。這些native方法中,必須有兩個(gè)native方法分別和 xxxInitialize()和 xxxTerminate()對(duì)應(yīng),其它的 native方法分別和*.h中要被用到的函數(shù)對(duì)應(yīng)。下面就是一個(gè)這樣的類聲明的例子,
在這個(gè)例子中,通過(guò)System.load()函數(shù)裝載的C/C++動(dòng)態(tài)庫(kù)libjnirankine.dll就是JNI要生成的動(dòng)態(tài)庫(kù)。這個(gè)動(dòng)態(tài)庫(kù)實(shí)現(xiàn)了這個(gè)Java類中的所有native函數(shù),而這些native函數(shù)分別調(diào)用了Matlab程序編譯結(jié)果動(dòng)態(tài)庫(kù)中的函數(shù)。
圖3 一個(gè)包含native函數(shù)的Java類的例子Fig.3 A Java class example with native methods
②通過(guò)javac命令將這個(gè)Java類進(jìn)行編譯生成jniRankine.class,然后調(diào)用javah–jni jniRankine生成一個(gè)*.h文件jniRankine.h。javah工具將所有native函數(shù)轉(zhuǎn)化為了JNI中的C/C++函數(shù)。這時(shí)候需要開發(fā)者手動(dòng)生成一個(gè)jniRankine.c或者jniRankine.cpp來(lái)實(shí)現(xiàn)jniRankine.h中的所有函數(shù)。jniRankine.c或者jniRankine.cpp必須包含Matlab程序編譯結(jié)果中的*.h文件,然后在jniRankine.c或者jniRankine.cpp中的各個(gè)函數(shù)中調(diào)用對(duì)應(yīng)的Matlab程序編譯結(jié)果中的C/C++函數(shù)。這樣就完成了JNI的編程。最后通過(guò)在Matlab中運(yùn)行如下mbuild命令編譯jniRankine.h以及jniRankine.c或者jniRankine.cpp,并鏈接Matlab程序編譯結(jié)果庫(kù),生成 libjnirankine.dll,
mbuild-I“C:Program FilesJavajdk1.7.0_05include” -I“C:Program FilesJavajdk1.7.0_05includewin32” jnirankine.cpp rankineDll.exports rankineDll.lib
-link shared-output libjnirankine
在這個(gè)命令中I參數(shù)后面是JDK的安裝路徑,rankine Dll.exports和rankineDll.lib是Matlab程序編譯的結(jié)果,libjnirankine是編譯結(jié)果。
③最后在Java圖形界面程序中就可以像使用一般的Java類一樣調(diào)用jniRankine類中的方法進(jìn)而應(yīng)用Matlab程序中的算法了。必須保證Matlab編譯結(jié)果中的*.dll文件在java.library.path中可以找到。
文中使用第1章中描述的兩種方法分別實(shí)現(xiàn)了計(jì)算理想朗肯循環(huán)的熱力學(xué)性質(zhì)的程序,程序比較簡(jiǎn)單,方便讀者明白程序結(jié)構(gòu)和流程。程序的開發(fā)環(huán)境為Eclipse和Matlab。在開發(fā)機(jī)器上安裝了JDK1.7.0_05來(lái)支持Eclipse環(huán)境和第一種方法中的Java包的編譯;在開發(fā)機(jī)器上還安裝了Microsoft Visual Studio10.0 for C++來(lái)支持第二種方法中C++程序的編譯。
圖4 理想朗肯循環(huán)的熱力學(xué)性質(zhì)計(jì)算程序的圖形界面Fig.4 GUI of thermodynamic efficiency of Ideal Rankine Cycle calculating program
程序的界面通過(guò)使用SWT圖形開發(fā)技術(shù)開發(fā),如圖4所示,在WindowsXP操作系統(tǒng)上運(yùn)行時(shí),SWT程序界面風(fēng)格和WindowsXP保持一致。在窗口的左邊部分是計(jì)算時(shí)的輸入?yún)?shù),“Load Defaults”按鈕會(huì)自動(dòng)給各個(gè)輸入?yún)?shù)填充默認(rèn)值。點(diǎn)擊 “Calculate”按鈕程序就會(huì)調(diào)用Matlab程序的算法進(jìn)行熱力學(xué)性質(zhì)的計(jì)算,并將計(jì)算結(jié)果顯示在窗口的右半部分的輸入框中。
Matlab的基本構(gòu)成和功能決定了Java-Matlab混合編程的可行性,利用這種混合開發(fā)技術(shù)可以開發(fā)出功能強(qiáng)大,界面友好,具有良好擴(kuò)展性和維護(hù)性的模塊化的科學(xué)計(jì)算程序。這種混合開發(fā)技術(shù)可以使得進(jìn)行圖形界面開發(fā)的Java程序員和進(jìn)行數(shù)值運(yùn)算開發(fā)的Matlab程序員分離開來(lái),彼此專注于自己擅長(zhǎng)的方面,降低的開發(fā)難度,提高了開發(fā)效率。
[1]Hanselman D,Littlefield B.精通MATLAB7[M].北京:清華大學(xué)出版社,2006.
[2]李傳軍.C語(yǔ)言與MATLAB接口--編程與實(shí)例[M].北京:北京郵電大學(xué)出版社,2004.
[3]羅星月.Matlab與C語(yǔ)言程序的應(yīng)用編程接口[EB/OL].(2007).http://www.builder.com.cn/2007/1030/591033.shtml.
[4]Muller Held.JMatLink[EB/OL].(2006).www.held-muellerde/JMatLink/.
[5]The Mathworks,Inc.Matlab幫助文檔:Matlab builder for Java[S].2007
[6]廖云伢,王建新,盛羽.基于Java與Matlab集成的虛擬實(shí)驗(yàn)平臺(tái)的設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)應(yīng)用,2007,27(2):394-399.LIAO Yun-ya,WANG Jian-xin,SHENG Yu.Design and implementation of virtual lab platform based on integration of java and matlab[J].Journal of Computer Applications,2007,27(2):394-399.
[7]張崇明,汪春梅,朱品昌,等.使用Java擴(kuò)展Matlab[J].計(jì)算機(jī)工程與設(shè)計(jì),2006,27(9):1563-1565.ZHANG Chong-ming,WANG Chun-mei,ZHU Pin-chang,et al.Extending matlab using java[J].Computer Engineering and Design,2006,27(9):1563-1565.