摘 要: 隨著計算機普及率的提升以及軟件行業(yè)的飛速發(fā)展,計算機語言也越來越受到廣大計算機愛好者和計算機軟件開發(fā)人員的關(guān)注,。同時越來越多的服務(wù)要求跨平臺的實現(xiàn),。當(dāng)前比較流行的兩大語言VC++和Java幾乎可以開發(fā)所有基于B/S架構(gòu)和基于C/S架構(gòu)的軟件項目。它們各有所長,,如果能將Java和VC有效地結(jié)合起來,,實現(xiàn)二者的互相調(diào)用,那將可以取長補短,,同時可以避免許多重復(fù)的工作,,提高編程的效率,。
關(guān)鍵詞: Java; VC; DLL; MFC; 漢字編碼
雖然Java和VC++是當(dāng)前兩大主流的編程語言,但是如果兩者之間不能有效結(jié)合,,實現(xiàn)相互調(diào)用的話,,勢必會給編程人員的工作帶來諸多不便,增加許多的重復(fù)工作,,甚至有可能造成整個項目的擱淺,。另外,不同語言之間的互相調(diào)用還可以有效地利用現(xiàn)有程序,并且不需要一遍一遍地撰寫類似的程序代碼,。為此,,本文引人了VC++中的動態(tài)鏈接庫文件,通過實例闡述了如何在Java中成功調(diào)用VC++動態(tài)鏈接庫的問題[1],。
1 技術(shù)介紹
1.1 動態(tài)鏈接庫DLL
動態(tài)鏈接庫DLL好比一個封裝起來的“倉庫”,DLL是Dynamic Link Library的縮寫,,其中封裝了一些或者部分可以被共享的例程和資源,采用動態(tài)的連接方式就能夠被其他程序動態(tài)裝載,、運行以完成某些特定的功能,。
采用動態(tài)鏈接庫進行軟件開發(fā),具體優(yōu)勢主要有下面幾點:
(1)對硬件資源方面的要求比較小
在程序開發(fā)過程中,,經(jīng)常遇到多個程序調(diào)用同一個函數(shù)庫的情況,,這時如果使用動態(tài)鏈接庫,就可以大大減少在磁盤和物理內(nèi)存中重復(fù)代碼的加載,。只有當(dāng)生成的EXE 文件確實要調(diào)用該DLL模塊時,,系統(tǒng)才會將其加載到內(nèi)存空間中去。
(2)項目體系結(jié)構(gòu)模塊化開發(fā)
程序結(jié)構(gòu)模塊化對項目開發(fā)有著重要的作用,,能夠方便項目的管理與功能的定制,。動態(tài)鏈接庫的設(shè)計包含這種思想。另外,,動態(tài)鏈接庫支持多語言,。這樣可以有更廣闊的應(yīng)用平臺,方便開發(fā)程序的移植,,也可以在不同的開發(fā)平臺上調(diào)用,。通常當(dāng)開發(fā)的系統(tǒng)為龐大系統(tǒng),避免不了有許多重復(fù)類型的功能,,這時如果將這些類似的功能單獨做成DLL,,將可以大大減少開發(fā)的工作量和提高開發(fā)的速度[2]。
(3)軟件維護方便
當(dāng)動態(tài)鏈接庫中的函數(shù)需要更新或修復(fù)時,,采用動態(tài)鏈接庫更方便,。因為部署及安裝動態(tài)鏈接庫在此就不要求重新建立程序與該DLL 的連接。此外,,如果多個程序使用同一個DLL,,則多個程序都將從該更新或修復(fù)中獲益,。當(dāng)使用定期更新或修復(fù)的第三方DLL 時,此問題可能會更頻繁地出現(xiàn),,升級到DLL 就可以更容易解決這些問題,。
(4)功能實現(xiàn)的細節(jié)隱藏
考慮到一些重要技術(shù)的保密和知識產(chǎn)權(quán)的保護,在某些情況下,,通常將項目中一些功能實現(xiàn)的具體細節(jié)隱藏起來,即希望里面的部分代碼不被公開,,這時動態(tài)鏈接庫就是一項非常不錯的實現(xiàn)方法,。動態(tài)鏈接庫可以被其他應(yīng)用程序訪問調(diào)用,但將代碼的具體細節(jié)完全隱藏起來,。另外,,DLL的語言無關(guān)性也是很重要的一個方面。正是由于動態(tài)鏈接庫DLL與語言無關(guān)的這個特點,,故用VC++創(chuàng)建的DLL可以被其他任何支持動態(tài)鏈接庫的編程語言調(diào)用, 比如VB,、Delphi、PD[3]等,。
1.2 Java本地編程接口JNI
JNI(Java Native Interfacejava)其實就是指Java本地程序接口,,屬于JDK中的一部分。當(dāng)Java程序中有需要調(diào)用通過VC++語言編寫的DLL時,,此時最佳選擇就是使用JNI技術(shù),。通過使用Java本地接口書寫程序,可以確保代碼在不同的開發(fā)平臺上方便移植,。JNI使得運行于Java虛擬機的代碼可以操作用C,、C++或者匯編等書寫的應(yīng)用程序或庫,同時也可以通過調(diào)用相應(yīng)的接口函數(shù)將Java虛擬機內(nèi)嵌到本地應(yīng)用程序中,。
特別需要提醒的是,,只要有下面幾種情況中的任何一種出現(xiàn)時,程序員就需要利用JNI來進行處理:(1)所開發(fā)的應(yīng)用程序要使用到與平臺相關(guān)的屬性,, 但Java標(biāo)準(zhǔn)類庫不支持對這些屬性的處理,; (2)已經(jīng)擁有了利用其他編程語言實現(xiàn)的應(yīng)用程序或庫,希望用Java 直接調(diào)用這些應(yīng)用程序或庫來實現(xiàn); (3)程序中的某個模塊對運行的時間效率要求很高,,此時希望用比較低級的語言(如匯編)來實現(xiàn),,同時希望在Java應(yīng)用程序中使用這個模塊[4]。
2 設(shè)計與實現(xiàn)
2.1 設(shè)計步驟
使用JNI在Java中調(diào)用VC++寫的DLL有以下幾個步驟:(1)創(chuàng)建Java類,;(2)編譯Java代碼并生成頭文件,;(3)開發(fā)DLL并實現(xiàn)方法;(4)編譯動態(tài)鏈接庫,;(5)測試運行程序,。
2.2 設(shè)計實例
2.2.1 無包情況
(1)在Java中寫調(diào)用VC的代碼,,具體如下:
public class JieCheng{
static{
System.loadLibrary("JieCheng");
//注意:不寫擴展名,名字要與DLL的文件名一致
}
public native static int jiecheng(int n); //聲明native方法
public static void main(String args[]){
int s;
JieCheng jc=new JieCheng();
s=jc.jiecheng(5);
System.out.println(s); //聲明main法
}
}
(2)在運行彈出的輸入框中輸入cmd進入dos界面,,通過cd命令進入到安裝Java的路徑下面的bin中,,假設(shè)安裝目錄是D:\Program Files\Java\jdk1.6.0_10\bin,把JieCheng.java文件移到D:\Program Files\Java\jdk1.6.0_10
\bin目錄下,,輸入javac JieCheng.java,,可以看到在該目錄下生成了JieCheng.class的文件。輸入javah JieCheng生成了JieCheng.h文件,。具體如下:
#include <jni.h>
/* Header for class JieCheng */
#ifndef _Included_JieCheng
#define _Included_JieCheng
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JieCheng
* Method: jiecheng
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_JieCheng_jiecheng
(JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
(3)在VC下創(chuàng)建DLL文件,名字一定要是System.loadLibrary("JieCheng")中的JieCheng,,把JieCheng.h文件直接復(fù)制到該VC文件下,同時把jni.h,jni_md.h復(fù)制到VC工程下,。在JieCheng.cpp文件下實現(xiàn)在Java中聲明過的方法,,注意方法名一定要與JieCheng.h中聲明的方法一致,在方法中寫入代碼如下:
#include"JieCheng.h"
JNIEXPORT jint JNICALL Java_JieCheng_jiecheng(JNIEnv *, jclass, jint n)
{
int i,s;
s=1;
for(i=1;i<=n;i++){
s=s*i;}
return s;
}
(4)在VC下編譯生成JieCheng.dll文件,,把該文件直接復(fù)制到Java的安裝目錄下面的bin目錄下:D:\Program Files\Java\jdk1.6.0_10\bin,。
(5)把在VC下編譯生成的JieCheng.dll文件直接復(fù)制到Java的安裝目錄的bin目錄下:D:\Program Files\Java\jdk1.6.0_10\bin。運行命令:java JieCheng,,本例中,,JieCheng函數(shù)用于求一個數(shù)的階乘,所以在屏幕上顯示的結(jié)果是“120”,。
2.2.2 有包情況
有包的情況與上面介紹的無包情況大致相同,。但需要特別強調(diào)、引起注意的地方是:首先需要在Java的安裝目錄bin下創(chuàng)建包名文件夾,,假設(shè)創(chuàng)建的包名文件夾的名稱為NegerVector,,然后把.java文件放在此文件夾中。接下來就是進入DOS環(huán)境下運行兩個命令,,首先運行:javac NegerVector\ JieCheng.java,;然后運行:javah Neger Vector.JieCheng。其他的可以參照無包情況了,,因為接下來與無包的情況基本相同,。
在許多大型項目的開發(fā)過程中,從提高開發(fā)效率以及實現(xiàn)代碼重用的角度來看,,跨平臺服務(wù)的開發(fā)是未來的發(fā)展趨勢,,從而經(jīng)常需要在Java程序中調(diào)用VC中的DLL。本文從JNI技術(shù)出發(fā),,通過簡單的實例詳細闡述了JNI調(diào)用VC++寫的DLL的程序,,解決了Java與VC的有效結(jié)合,實現(xiàn)了它們之間的相互調(diào)用。
參考文獻
[1] 王志文,,夏秦,,李平均.Java程序設(shè)計(修訂本)[M].西安:西安交通大學(xué)出版社,2005.
[2] 孫文華.一種基于Java編程的臟字過濾器的設(shè)計[J].微型機與應(yīng)用,2012,31(9):18-19,23.
[3] 王敏,邵定宏,陸金桂.動態(tài)鏈接庫技術(shù)及其應(yīng)用實[J].微計算機信息,2006,22(27):272-274.
[4] 宋曉字,,王永會. Visual C++高級編程技術(shù)與實例[M].北京:中國水利水電出版社,,2006.