一、 注冊JNI函數
1、 靜態方法
一般使用javah進行編譯,生成很長的文件名和函數名字,這個書寫不方便,影響運行效率。
2、 動態注冊
使用JNINativeMethod的結構,定義如下:
typedef struct {
const char* name; //java中函數的名字,不帶包路徑
const char* signature ; //java函數的簽名信息
void * fnPtr; //JNI層對應函數的函數指針
}JNINativeMethod;
AndroidRunTime類提供了一個registerNativeMethods函數來完成注冊工作。
當java通過System.loadLibrary加載完JNI動態庫后,緊接着會查找庫中一個叫做JNI_OnLoad的函數,如果有就調用它,而自動注冊工作就在這里完成了。
二、通過JNIEnv操作jobject
1、 jfieldID 和 jmethodID 表示java類的成員變量和成員函數
jfieldID GetFieldID(jclass clazz, const char* name , const char *sig);
jmethodID GetMethodID(jclass clazz, const char* name, const char* sig);
其中 jclass代表java類
name表示成員函數或者變量名
sig這個為函數和變量的簽名信息
如果每次操作jobject都去查詢jmethodID或者jfieldID會影響程序的運行效率,所以我們在初始化的時候將ID保存起來供后續使用。
2、使用jfieldID和jmethodID
代碼如下:
通過JNIEnv輸出CallVoidMethod的函數,如下:
其中type對應java函數的返回值類型,例如:CallIntMethod,CallVoidMethod等。
上面針對的是非static函數,如果想掉用java中的static函數,則JNIEnv輸出CallStatic<type>Method系列函數。
通過jfieldID操作成員變量,如下:
三、函數簽名
Java支持函數重載,可以定義同名但是不同參數的函數,但僅僅更具函數名是無法找到具體的函數,jni中將參數和返回值類型組合作為一個函數的簽名信息,有了簽名信息就可以找到java中的函數了。
雖然函數簽名很容易寫錯,但是java提供了一個javap的工具,幫助函數或變量生成簽名信息,用法如下:
javap –s -p XXX
其中XXX為編譯后的class文件,s表示內部數據類型的簽名信息,P表示打印所有的函數和成員的簽名信息,默認只會打印public成員函數和函數的簽名信息。