利用JNative實現Java調用動態庫

由於項目要求,需要用Java調用windows的dll文件,查了一下,如果用JNI的話是比較麻煩的,在sourceforge.net上搜索了一下 “Java dll”,首先出現的是Jnative,於是決定用它,後來也試了些別的,但還是JNative好使,簡單總結如下: 

Java調用動態庫所需要關心的問題: 
l         如何裝載dll文件,以及如何定位所要使用的方法; 

l         數據類型是如何對應的; 

l         如何給使用的方法傳遞參數; 

l         如何獲取返回的值。 

JNative INFO: 
Resource URL: http://jnative.sourceforge.net/ 

Source Code: http://sourceforge.net/projects/jnative 

Detailed Review: http://jnative.free.fr 

JavaDOC: http://jnative.free.fr/docs/ 

Version:1.3 

一個開源的組件,通過它調用已有動態庫中的方法就非常的方便,支持CallBack 。 

爲什麼選擇JNative 
同類的開源組件相對活躍的還有,JNA ( Java Native Access ), Jawin,Nativecall,etc.但是Jnative 相對更容易使用,它對數據類型的處理做的更好。 

l         JNA 需要用戶對所使用的DLL文件事先進行封裝,才能裝載。另外需要在一個java接口中描述目標DLL中的函數與結構,從而使JNA自動實現Java接口到native function的映射,較麻煩。 

l         Nativecall 暫時還不知道如何裝載dll文件。 

l         Jawin 數據類型匹配相當敏感,它採用一種叫做”instruction string”的格式來傳遞參數,還沒有完全理解。 

How to: 
解壓JNative-1.3.2.zip 獲得三個文件,分別是:JNativeCpp.dll,libJNativeCpp.so,JNative.jar 。 


JNativeCpp.dll Windows下用的,拷到windows / system32目錄下; 

libJNativeCpp.so Linux下的咚咚; 

JNative.jar 這是一個擴展包,將其copy到C:\jdk\jre\lib\ext 下(我的目錄結構),系統會自動加載。 

結構映射(Structure Mapping) 




Type 
Length 
JNative class 

DWORD 

org.xvolks.jnative.misc.basicStructures.LONG 

HWND 

org.xvolks.jnative.misc.basicStructures.HWND 

COLORREF 

org.xvolks.jnative.misc.basicStructures.LONG 

COLORREF* 

org.xvolks.jnative.pointers.Pointer 

LPARAM 

org.xvolks.jnative.misc.basicStructures.LPARAM 

LPCCHOOKPROC 

org.xvolks.jnative.util.Callback 

LPCTSTR 

org.xvolks.jnative.pointers.Pointer 


一些關鍵的類及方法 

Class 
作用 
一般用到的方法(參數略,參考Doc) 

org.xvolks.jnative.Jnative 
裝載dll文件,定位函數 
JNative(),setParameter(),setRetVal(),getRetVal() etc. 

org.xvolks.jnative.pointers.Pointer 
替代本地函數中的的指針,需要先申請一塊內存空間,才能創建 
Pointer(),dispose() 

org.xvolks.jnative.pointers.memory.MemoryBlockFactory 
申請一塊內存空間 
createMemoryBlock() 

org.xvolks.jnative.exceptions.NativeException 
拋出裝載,定位等方面的異常 


org.xvolks.jnative.Type 
列舉和管理Jnative需要的不同的數據類型 




(二) 

簡單測試,Javadoc 下和官方網上有些例子,下面的是我隨便從IC讀卡程序中找了個DLL進行的測試: 
SCReader.dll 下的SCHelp_HexStringToBytes()函數原型 
SCREADER_API WINAPI long SCHelp_HexStringToBytes( 

LPCTSTR pSrc, 

BYTE* pTar, 

int MaxCount 

); 

注意:dll文件需要放到System32下,否則可能找不到 



通過Jnative 用java 來調用代碼如下: 

package onlyfun.dllcall; 
import org.xvolks.jnative.JNative; 
import org.xvolks.jnative.exceptions.NativeException; 
import org.xvolks.jnative.pointers.Pointer; 
import org.xvolks.jnative.pointers.memory.MemoryBlockFactory; 
import org.xvolks.jnative.Type; 
public class UserCall { 
    /** 
    * return 轉換成功的字節數 
    */ 
    static JNative Something = null; 
    static Pointer pointer; 
    public String getSomething(String pSrc, Pointer pTar, int MaxCount) throws NativeException, IllegalAccessException{ 
      
       try{ 
           if(Something == null){ 
              pTar = new Pointer(MemoryBlockFactory.createMemoryBlock(36)); 
              Something = new JNative("SCReader.DLL", "SCHelp_HexStringToBytes"); 
// 利用org.xvolks.jnative.JNative 來裝載 SCReader.dll,並利用其SCHelp_HexStringToBytes方法 
              Something.setRetVal(Type.INT); 
// 指定返回參數的類型 
           } 
           int i=0; 
           Something.setParameter(i++,pSrc); 
           Something.setParameter(i++,pTar); 
           Something.setParameter(i++,MaxCount); 
           System.out.println("調用的DLL文件名爲:"+Something.getDLLName()); 
           System.out.println("調用的方法名爲:"+Something.getFunctionName()); 
//傳值 
           Something.invoke();//調用方法 
           return Something.getRetVal(); 
       }finally{ 
           if(Something!=null){ 
              Something.dispose();//釋放 
           } 
       } 
    } 
    public Pointer creatPointer() throws NativeException{ 
       pointer = new Pointer(MemoryBlockFactory.createMemoryBlock(36)); 
       pointer.setIntAt(0, 36); 
       return pointer; 
    } 

    public static void main(String[] args) throws NativeException, IllegalAccessException { 
       UserCall uc = new UserCall(); 
       String result = uc.getSomething("0FFFFF", uc.creatPointer(), 100); 
       System.err.println("轉換成功的字節數爲:"+result); 
       TestCallback.runIt(); 
    } 
}

發佈了184 篇原創文章 · 獲贊 48 · 訪問量 31萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章