一.JNI?的開發流程
JNI 開發
步驟:
1.編寫native 方法
2.javah 命令,生成.h 文件
java_類的全名_方法名
或者自己手寫
3.復制.h 頭文件到cpp 工程
4.復制jni.h 和jni_md.h
5.實現.h 頭文件中的聲明函數
6.生成一個dll 動態庫
7.在java中加載動態庫
8.觸發native函數
二.JNI的數據類型
在JNI的世界里也存在類似的數據類型,與Java比較起來,其范圍更具嚴格性,如下:
1、primitive types ----基本數據類型,如:int、 float 、char等基本類型
2、reference types----引用類型,如:類、實例、數組。
特別需要注意:數組------ 不管是對象數組還是基本類型數組,都作為reference types存在。
1、primitive types(基本數據類型)映射參見下表:
這些基本數據類型都是可以在Native層直接使用的 。
2、reference types(引用數據類型)映射參見下表
注意:
1、引用數據類型則不能直接使用,需要根據JNI函數進行相應的轉換后,才能使用
2、多維數組(包括二維數組)都是引用類型,需要使用jobjectArray類型存取其值 ;
例如:二維整型數組就是指向一位數組的數組,其聲明使用方式如下:
//獲得一維數組?的類引用,即jintArray類型
jclass?intArrayClass?=?env->FindClass("[I");
//構造一個指向jintArray類一維數組的對象數組,該對象數組初始大小為dimion
jobjectArray?obejctIntArray??=??env->NewObjectArray(dimion?,intArrayClass?,?NULL);
...//具體操作
另外,關于引用類型的一個繼承關系如下,我們可以對具有父子關系的類型進行轉換:
類描述符是類的完整名稱(包名+類名),將原來的 . 分隔符換成 / 分隔符。
例如:在java代碼中的java.lang.String類的類描述符就是java/lang/String
其實,在實踐中,我發現可以直接用該類型的域描述符取代,也是可以成功的。
例如:jclass intArrCls = env->FindClass("java/lang/String")
等同于jclass intArrCls = env->FindClass("Ljava/lang/String;")
數組類型的描述符則為,則為: ?[ + 其類型的域描述符 ? ? ? ?(后文說明)
例如:
int [ ] ? ? 其描述符為[I
float [ ] ? 其描述符為[F
String [ ] ?其描述符為[Ljava/lang/String;
1、基本類型的描述符已經被定義好了,如下表所示:
2、引用類型的描述符
一般引用類型則為 L + 該類型類描述符 + ;(注意,這兒的分號“;”只得是JNI的一部分,而不是我們漢語中的分段,下同)
例如:String類型的域描述符為 Ljava/lang/String;
對于數組,其為 : ?[ + 其類型的域描述符 + ;
int[ ] ? ? 其描述符為[I
float[ ] ? 其描述符為[F
String[ ] ?其描述符為[Ljava/lang/String;
Object[ ]類型的域描述符為[Ljava/lang/Object;
多維數組則是 n個[ +該類型的域描述符 , N代表的是幾維數組。例如:
int ?[ ][ ] 其描述符為[[I
float[ ][ ] 其描述符為[[F
將參數類型的域描述符按照申明順序放入一對括號中后跟返回值類型的域描述符,規則如下: (參數的域描述符的疊加)返回
類型描述符。對于,沒有返回值的,用V(表示void型)表示。舉例如下:
Java層方法 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? JNI函數簽名
String test ( ) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Ljava/lang/String;
int f (int i, Object object) ? ? ? ? ? ? ? ? ? ? ? ? ? ?(ILjava/lang/Object;)I
void set (byte[ ] bytes) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?([B)V
在編程時,如果是利用javah工具的話,這些都不需要我們手動編寫對應的類型轉換,如果不能用javah工具,就只能手動的
進行類型轉換了。