8/09/2008

[Java] 關於Java調用dll的方法

Java语言本身具有跨平台性,如果通過Java調用DLL的技术方便易用,使用Java開發前台界面可以更快速,也能帶来跨平台性。

    Java調用C/C++寫好的DLL庫時,由於基本數據類型不同、使用字節序列可能有差異,所以在參數傳遞過程中容易出現問題。

    使用Java調用DLL動態鏈接庫的方案通常有三種︰JNI, Jawin, Jacob.







 其中JNI(Java Native Interface)Java語言本身提供的調用本地已編譯的函數庫的方法,本身具有跨平台性,可以在不同的機器上調用不同的本地庫。JawinJacob都是sourceforge.net的开源项目,都是基于JNI技术的依赖Windows的实现,使得在Windows平台下使用COMDLL的更加方便。

一、JNI




JNI的應用方案是基於Java類和本地函數相映射的。其使用DLL的步驟還是相對比較麻煩,不但涉及到Java編程,還涉及到C/C++編程。

JNI的使用步驟是︰

1.編寫Java類,用該類將DLL對外提供的函數服務進行聲明,其中的Java方法均聲明為native,其方法簽名可以自定義,不用實現函數體。

2.Javah工具將該Java類生成對應的.h頭文件。

3.最重要的比較麻煩的一步︰編寫C/C++代碼實現.h頭文件中聲明的函數,該C/C++代碼中包含jni.h頭文件,並且編寫代碼時使用其中定義好的 數據類型作為函數的輸入和返回數據類型進行編程。用這種方法實現數據類型轉換。例如數據類型︰boolean(java)    jboolean(jni.h: typedef unsigned char jboolean),在自己編寫的C/C++代碼中使用數據類型jboolean映射Java中的boolean類型。在該步驟中,可以在C/C++代碼 中調用已經存在的DLL庫。

4.另外編寫的Java代碼時就可以使用該Java類了。

在第3步中,編寫C/C++函數時,可以使用一個叫interface pointerenv指針來調用JNI提供的一系列(很多)函數,用這些函數來訪問JVM的對象和數據。

使用JNI的缺點︰使用比較麻煩,需要對已有的DLL進行封裝,需要對C/C++比較了解。

使用JNI的優點︰可以跨平台調用本地庫。


二、Jawin 


官方文檔(Jawin使用DLL)http://jawinproject.sourceforge.net/jawinuserguide_dll.html


Jawin的應用方案是基於函數調用時采用原始字節流傳遞數據的。就是在Java中指明一個DLL中的某個函數後,透過原始位元組流(需要考慮參數數據類型所占的存儲位元組數及系統使用的位元組序列)傳遞給該DLL函數需要的參數,其返回值也是透過原始位元組流解析的模式獲得正確的值。

Jawin的使用步驟︰

1.環境配置︰下载JawinJawin.dll放入工程目錄下;Jawin.jar相關jar文件加入到運行庫中(LibPath或者Eclipse下配置工程的BuildPath-AddLibrary)

2.獲得函數指針︰new FuncPtr(“DllFileName.DLL”, “dllFunctionName”);

3.LittleEndianOutputStream將函數需要的參數寫入到一個原始字節流NakedByteStream

4.最重要的一步︰調用FuncPtr.invoke()。傳入參數比較複雜。

5.解析上一步的返回值(字節數組)

4步中傳入的參數包括︰

1.指令字符串。一個”XXX:Y:ZZZ”格式的字元串。其含義分別是傳入參數中的每個位元組的數據類型意義、返回值的類型、需要從傳入指標中讀取的數據(inout類型參數)。比如︰

函數簽名int func(int, int, struct s*, char*); //其中struct s*調用完函數後需要讀出,struct s所占字節數為16

其指令字符串為︰IIP16G:I:L4L4n16L4。該字元串在解析返回值(位元組數組)時,首先應該是返回類型I對應的4個位元組,然後是inout類型的參數中n16對應的16個位元組。

其中字符串的意義可以在Jawin提供的文件instructions.h中找到,或者在官方文檔(Jawin數據指令)中找到常用的一些指令字符串的意義。

2.傳入參數的總字節大小。

3.前面寫好的傳入參數的原始字節流。

4.一個object數組。

5.ReturnFlags,用以根據C/C++返回值將C/C++的錯誤轉換為Java的異常並拋出。其中CHECK_NONE表示不檢 查;CHECK_FALSECHECK_WIN32分別表示返回0FALSESUCCESS,根據是否出錯決定是否拋出異 常;CHECK_HRESULT表示使用COM模型中的HRESULT作為返回值,其錯誤碼可以配置。

使用Jawin的缺點︰不方便調試,幾乎所有的錯誤都拋出同樣的異常COMException;需要對數據類型的轉換比較了解;不能跨平台,對Windows的依賴性比較強。

使用Jawin的優點︰方便使用,不用進行C/C++開發,不用對原始DLL進行封裝就可以方便使用。


三、Jacob


JacobJava-Com Bridge的縮寫,也可以用來調用DLL。其底層也是使用JNI實現,也具有Windows的平台倚賴性,由於網上有人反映其易用性不如jawin,所以沒有深入了解。


沒有留言:

張貼留言