Android NDK(四)- JNI 注冊(cè) Native 方法

靜態(tài)注冊(cè)

靜態(tài)注冊(cè)的格式如下:
extern "C" JNIEXPORT [JNI參數(shù)類型] JNICALL Java_[包名]_[類名]_[方法名](JNIEnv* env, jobject, [JNI參數(shù)類型,參數(shù)名])
包名也用 _ 分隔。
包名、類名、方法名必須和 Java 中的一模一樣。

例子:

extern "C" JNIEXPORT jstring JNICALL Java_com_sample_MainActivity_stringFromJNI(JNIEnv* env, jobject this_obj) {
    std::string hello = "Hello World from C++";
    return env->NewStringUTF(hello.c_str());
}

缺點(diǎn):

  • 方法名很長(zhǎng)
  • 效率低。首次調(diào)用 Java native 方法時(shí)需要根據(jù)方法名在 JNI 中查找對(duì)應(yīng)的本地 C++ 函數(shù)并建立對(duì)應(yīng)關(guān)系,這個(gè)過(guò)程是比較耗時(shí)的。

優(yōu)點(diǎn):

  • 編寫不方便的缺點(diǎn) Android Studio 已經(jīng)幫我們解決,可以先編寫 Java native 方法,然后根據(jù)提示自動(dòng)生成對(duì)應(yīng)的本地 C++ 方法。
  • 閱讀代碼方便,本地 C++ 方法和 Java native 方法可以互相跳轉(zhuǎn)查看。

動(dòng)態(tài)注冊(cè)

在調(diào)用 System.loadLibrary 加載庫(kù)文件時(shí),系統(tǒng)回調(diào) JNI_OnLoad() 函數(shù)。
可以在 JNI_OnLoad 中做一些初始化操作,可以用 RegisterNatives 方法注冊(cè) Java native 方法。

jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint nMethods);

這樣的話,提前建立 Java native 方法和本地 C++ 方法的關(guān)系,在調(diào)用 Java native 方法的時(shí)候無(wú)需再查找并建立關(guān)系,就會(huì)比較快。

例子:

jstring stringFromJNI(JNIEnv* env, jobject this_obj) {
    std::string hello = "Hello World from C++";
    return env->NewStringUTF(hello.c_str());
}

static int registerNatives(JNIEnv *env) {

    // 要注冊(cè)的 java 類的路徑(完整的包名和類名)
    const char *className = "com/teletian/sample/MainActivity";

    /*
     * 要注冊(cè)的函數(shù)列表
     * 參數(shù):
     * 1. java 中用 native 關(guān)鍵字聲明的函數(shù)名
     * 2. 函數(shù)簽名,格式:(參數(shù)類型)返回類型
     * 3. C/C++ 中對(duì)應(yīng)函數(shù)的函數(shù)名(地址)
     * */
    const JNINativeMethod nativeMethods[] = {
            {"stringInJava", "()Ljava/lang/String;", (void *) stringFromJNI},
    };

    jclass clazz = env->FindClass(className);
    if (clazz == nullptr) {
        return JNI_FALSE;
    }
    int methodsCount = sizeof(nativeMethods) / sizeof(nativeMethods[0]);
    //注冊(cè)函數(shù) 參數(shù):java 類名,要注冊(cè)的函數(shù)數(shù)組,要注冊(cè)函數(shù)的數(shù)量
    if (env->RegisterNatives(clazz, nativeMethods, methodsCount) < 0) {
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = nullptr;
    if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return JNI_ERR;
    }
    assert(env != nullptr);
    //registerNatives -> env->RegisterNatives
    if (!registerNatives(env)) {
        return JNI_ERR;
    }

    return JNI_VERSION_1_6;
}

缺點(diǎn):

  • 代碼不夠簡(jiǎn)潔
  • 閱讀代碼不方便,本地 C++ 方法和 Java native 方法無(wú)法互相跳轉(zhuǎn)查看。

優(yōu)點(diǎn):

  • 流程清洗可控
  • 效率高。提前建立關(guān)系,首次調(diào)用方法時(shí)速度快
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容