Android JNI學(xué)習(xí)-函數(shù)動態(tài)注冊

前面JNI開發(fā)相關(guān)的也寫了幾篇博客,對java中native關(guān)鍵字定義的方法進(jìn)行注冊時,都是使用Javah命令生成對應(yīng)的Java _ 包名 _ 類名 _ 方法名,現(xiàn)在完全可以通過編譯器幫我們生成,我們?nèi)ヌ顚?yīng)的邏輯代碼即可,這種方式被稱為靜態(tài)注冊。今天來看一下新的方式:動態(tài)注冊

不同于靜態(tài)注冊中在Java類中定義好native方法后由編譯器生成JNI方法,動態(tài)注冊基本思想是在JNI_Onload()函數(shù)中通過JNI中提供的RegisterNatives()方法來將C/C++方法和java方法對應(yīng)起來, JNI_OnLoad ()函數(shù)會在我們調(diào)用 System.loadLibrary的時候回調(diào),注冊整體流程如下:

  1. 定義Java類中的native方法
  2. 編寫C/C++代碼, 實現(xiàn)JNI_Onload()方法
  3. 將Java 方法和 C/C++方法通過簽名信息對應(yīng)起來
  4. 通過JavaVM獲取JNIEnv, JNIEnv主要用于獲取Java類和調(diào)用一些JNI提供的方法
  5. 使用類名和對應(yīng)起來的方法作為參數(shù), 調(diào)用JNI提供的函數(shù)RegisterNatives()注冊方法

1、Java Native方法

public native String getStringFromC();

public native int getIntFromC(int index);

2、C/C++方法

jstring returnString(JNIEnv *env, jobject instance) {
    char *str = "I come from C++";
    return env->NewStringUTF(str);
}

jint returnInt(JNIEnv *env, jobject instance, jint index) {
    return index + 10;
}

3、JNINativeMethod

static JNINativeMethod gMethods[] = {
        {"getStringFromC", "()Ljava/lang/String;", (void *) returnString},
        {"getIntFromC",    "(I)I",                 (void *) returnInt}
};
  • 第一個參數(shù)對應(yīng)的native方法名
  • 第二個參數(shù)對應(yīng) native方法的描述
  • 第三個參數(shù)對應(yīng)的c++代碼里對應(yīng)的實現(xiàn)

通過這個數(shù)組將Java層函數(shù)和C/C++層代碼對應(yīng)起來

4、JNI_Onload

int JNI_OnLoad(JavaVM *vm, void *re) {
    JNIEnv *env;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return JNI_ERR;
    }

    jclass javaClass = env->FindClass("com/david/jnitestdemo/MainActivity");
    if (javaClass == NULL) {
        return JNI_ERR;
    }
    if (env->RegisterNatives(javaClass, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) < 0) {
        return JNI_ERR;
    }
    return JNI_VERSION_1_6;
}

env->RegisterNatives(javaClass, gMethods, sizeof(gMethods) / sizeof(gMethods[0])

第一個表示對應(yīng)jclass,第二個表示JNINativeMethod的數(shù)組,第三個是函數(shù)的數(shù)量

這樣就完成了簡單的JNI動態(tài)注冊Demo

對比下之前的靜態(tài)注冊:

//靜態(tài)注冊
extern "C" JNIEXPORT jstring JNICALL
Java_com_david_jnitestdemo_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
}
 
//動態(tài)注冊
jstring returnString(JNIEnv *env, jobject instance) {
}

相比較來說動態(tài)注冊的代碼會清爽一些,雖然多了JNI_OnLoad和JNINativeMethod,但是JNI_OnLoad基本可以只寫一次,JNINativeMethod每次有新增函數(shù)時才修改,所以個人感覺動態(tài)注冊寫代碼會更舒服些,也看個人習(xí)慣 ,好了就到這里了。 -

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容