摘 要: 隨著計算機普及率的提升以及軟件行業(yè)的飛速發(fā)展,計算機語言也越來越受到廣大計算機愛好者和計算機軟件開發(fā)人員的關(guān)注。同時越來越多的服務要求跨平臺的實現(xiàn)。當前比較流行的兩大語言VC++和Java幾乎可以開發(fā)所有基于B/S架構(gòu)和基于C/S架構(gòu)的軟件項目。它們各有所長,如果能將Java和VC有效地結(jié)合起來,實現(xiàn)二者的互相調(diào)用,那將可以取長補短,同時可以避免許多重復的工作,提高編程的效率。
關(guān)鍵詞: Java; VC; DLL; MFC; 漢字編碼
雖然Java和VC++是當前兩大主流的編程語言,但是如果兩者之間不能有效結(jié)合,實現(xiàn)相互調(diào)用的話,勢必會給編程人員的工作帶來諸多不便,增加許多的重復工作,甚至有可能造成整個項目的擱淺。另外,不同語言之間的互相調(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)存中重復代碼的加載。只有當生成的EXE 文件確實要調(diào)用該DLL模塊時,系統(tǒng)才會將其加載到內(nèi)存空間中去。
(2)項目體系結(jié)構(gòu)模塊化開發(fā)
程序結(jié)構(gòu)模塊化對項目開發(fā)有著重要的作用,能夠方便項目的管理與功能的定制。動態(tài)鏈接庫的設(shè)計包含這種思想。另外,動態(tài)鏈接庫支持多語言。這樣可以有更廣闊的應用平臺,方便開發(fā)程序的移植,也可以在不同的開發(fā)平臺上調(diào)用。通常當開發(fā)的系統(tǒng)為龐大系統(tǒng),避免不了有許多重復類型的功能,這時如果將這些類似的功能單獨做成DLL,將可以大大減少開發(fā)的工作量和提高開發(fā)的速度[2]。
(3)軟件維護方便
當動態(tài)鏈接庫中的函數(shù)需要更新或修復時,采用動態(tài)鏈接庫更方便。因為部署及安裝動態(tài)鏈接庫在此就不要求重新建立程序與該DLL 的連接。此外,如果多個程序使用同一個DLL,則多個程序都將從該更新或修復中獲益。當使用定期更新或修復的第三方DLL 時,此問題可能會更頻繁地出現(xiàn),升級到DLL 就可以更容易解決這些問題。
(4)功能實現(xiàn)的細節(jié)隱藏
考慮到一些重要技術(shù)的保密和知識產(chǎn)權(quán)的保護,在某些情況下,通常將項目中一些功能實現(xiàn)的具體細節(jié)隱藏起來,即希望里面的部分代碼不被公開,這時動態(tài)鏈接庫就是一項非常不錯的實現(xiàn)方法。動態(tài)鏈接庫可以被其他應用程序訪問調(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中的一部分。當Java程序中有需要調(diào)用通過VC++語言編寫的DLL時,此時最佳選擇就是使用JNI技術(shù)。通過使用Java本地接口書寫程序,可以確保代碼在不同的開發(fā)平臺上方便移植。JNI使得運行于Java虛擬機的代碼可以操作用C、C++或者匯編等書寫的應用程序或庫,同時也可以通過調(diào)用相應的接口函數(shù)將Java虛擬機內(nèi)嵌到本地應用程序中。
特別需要提醒的是,只要有下面幾種情況中的任何一種出現(xiàn)時,程序員就需要利用JNI來進行處理:(1)所開發(fā)的應用程序要使用到與平臺相關(guān)的屬性, 但Java標準類庫不支持對這些屬性的處理; (2)已經(jīng)擁有了利用其他編程語言實現(xiàn)的應用程序或庫,希望用Java 直接調(diào)用這些應用程序或庫來實現(xiàn); (3)程序中的某個模塊對運行的時間效率要求很高,此時希望用比較低級的語言(如匯編)來實現(xiàn),同時希望在Java應用程序中使用這個模塊[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文件直接復制到該VC文件下,同時把jni.h,jni_md.h復制到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文件,把該文件直接復制到Java的安裝目錄下面的bin目錄下:D:\Program Files\Java\jdk1.6.0_10\bin。
(5)把在VC下編譯生成的JieCheng.dll文件直接復制到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)代碼重用的角度來看,跨平臺服務的開發(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].西安:西安交通大學出版社,2005.
[2] 孫文華.一種基于Java編程的臟字過濾器的設(shè)計[J].微型機與應用,2012,31(9):18-19,23.
[3] 王敏,邵定宏,陸金桂.動態(tài)鏈接庫技術(shù)及其應用實[J].微計算機信息,2006,22(27):272-274.
[4] 宋曉字,王永會. Visual C++高級編程技術(shù)與實例[M].北京:中國水利水電出版社,2006.