JNA--Java呼叫DLL

mao906581468發表於2013-04-24


 

1、 起源

Java原生的呼叫本地函式(C/C++)的機制是JNI(JavaNative Interface),但是由於其使用的複雜,還需要寫C程式碼,對許多入門級程式設計師來說實在不是個好的選擇。JNA(Java Native Access)Sun公司主導開發的基於JNIjava呼叫原生函式的機制,是對JNI的再次封裝。其優點是,使用簡單,只需要編寫一個包含指定函式的介面即可。JNA提供了動態的C 語言編寫的轉發器,可以自動實現Java C 的資料型別對映。而不必像使用JNI一樣完全自己去做資料型別對映,不再需要編寫那個煩人的C 動態連結庫。當然,JNA相比於JNI,效率不高,會有部分效能損失,畢竟是對JNI的擴充套件。類似的優秀框架還有JNative

2、 資料型別對映(來源於JNA的官方JavaDoc文件首頁)

Java types must be chosen to match native types of the samesize. Following are the types supported by the JNA library. (簡單型別對映)

Java Type

C Type

Native Representation

boolean

int

32-bit integer (customizable)

byte

char

8-bit integer

char

wchar_t

platform-dependent

short

short

16-bit integer

int

int

32-bit integer

long

long long, __int64

64-bit integer

float

float

32-bit floating point

double

double

64-bit floating point

Buffer
  Pointer 

pointer

platform-dependent (32- or 64-bit  pointer to memory)

<T>[] (array of primitive  type)

pointer
  array

32- or 64-bit pointer to memory  (argument/return)
  contiguous memory (struct member)

 

In addition to the above types, which aresupported at the native layer, the JNA Java library automatically handles thefollowing types. All but NativeMapped and NativeLong are converted to Pointer before being passed to the native layer.(複雜型別對映)

String

char*

NUL-terminated array (native  encoding or jna.encoding)

WString

wchar_t*

NUL-terminated array (unicode)

String[]

char**

NULL-terminated array of C strings

WString[]

wchar_t**

NULL-terminated array of wide C  strings

Structure

struct*
  struct

pointer to struct (argument or  return) (or explicitly)
  struct by value (member of struct) (or explicitly)

Union

union

same as Structure

Structure[]

struct[]

array of structs, contiguous in  memory

Callback

<T> (*fp)()

function pointer (Java or native)

NativeMapped

varies

depends on definition

NativeLong

long

platform-dependent (32- or 64-bit  integer)

PointerType

pointer

same as Pointer

3、 Eclipse中使用DLL

Eclipse中,匯入JNAjar包(如jna-3.5.1.jar),在需要使用DLL的專案的根目錄下放置.dll檔案,使用例子如下:

Dll檔案為:MyDll.dll,其中申明的外部可呼叫方法有:

void   add1(int a,int b);

void   add2(int *a,int*b);//a和b是指向int型的指標

void   add3(int *a,int *b);//a和b是指向int[]的指標

void   add4(int a[],int b[]);

 

對應的java檔案JNATest.java:

importcom.sun.jna.ptr.IntByReference;

public interface JNATestextends Library {

 

   JNATest JNATestIntance = (JNATest) Native.loadLibrary(

                     " MyDll ", JNATest.class);

   //c中的函式void   add1(int a,int b);

   public void add1(int a,int b);

   

              //void  add2(int *a,int*b);//a和b是指向int型的指標

   public void add2(IntByReference a,IntByReference b);

   

              //void   add3(int *a,int *b);//a和b是指向int[]的指標

   public void add3(int []a,int []b);

   

               //void  add4(int a[],int b[]);

   public void add4(int []a,int []b);

 

   public static void main(String args[])

   {

      int a=9;

      int b=4;

      int array1={1,4,5};

      int array2={3,1,5};

     JNATest.JNATestIntance.add1(a,b);

     JNATest.JNATestIntance.add2(newIntByReference(a),new IntByReference(b));

     JNATest.JNATestIntance.add3(array1,array2);

     JNATest.JNATestIntance. add4(array1,array2);

   }

}

 

其中IntByReference在表示指向int型的指標,類似的還有ByteByReference, DoubleByReference,

 FloatByReference,LongByReference, NativeLongByReference, PointerByReference,ShortByReference,

W32API.HANDLEByReference, X11.AtomByReference,X11.WindowByReference

PointerByReference 類表示指向指標的指標。

 

當然,涉及指標時也可以使用Pointer這個類,它是一個單例,不允許用建構函式建立。可以使用PointerType自定義。具體實現參考JavaDoc文件。Pointer使用:

import com.sun.jna.ptr.IntByReference;

public interface JNATestextends Library {

 

   JNATest JNATestIntance = (JNATest) Native.loadLibrary(

                     "Sense2020Dll", JNATest.class);

   //c中的函式void   add1(int a,int b);

   public void add1(int a,int b);

   

              //void   add2(int *a,int*b);//a和b是指向int型的指標

   public void add2(Pointer a,Pointer b);

 

   public static void main(String args[])

   {

      int a=9;

      int b=4;

      JNATest.JNATestIntance.add1(a,b);

      JNATest.JNATestIntance.add2(newIntByReference(a). getPointer(),

                           newIntByReference(b).     getPointer());

      

   }

}

 


 

 

相關文章