Android NDK(四)- JNI 注册 Native 方法

静态注册

静态注册的格式如下:
extern "C" JNIEXPORT [JNI参数类型] JNICALL Java_[包名]_[类名]_[方法名](JNIEnv* env, jobject, [JNI参数类型,参数名])
包名也用 _ 分隔。
包名、类名、方法名必须和 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());
}

缺点:

  • 方法名很长
  • 效率低。首次调用 Java native 方法时需要根据方法名在 JNI 中查找对应的本地 C++ 函数并建立对应关系,这个过程是比较耗时的。

优点:

  • 编写不方便的缺点 Android Studio 已经帮我们解决,可以先编写 Java native 方法,然后根据提示自动生成对应的本地 C++ 方法。
  • 阅读代码方便,本地 C++ 方法和 Java native 方法可以互相跳转查看。

动态注册

在调用 System.loadLibrary 加载库文件时,系统回调 JNI_OnLoad() 函数。
可以在 JNI_OnLoad 中做一些初始化操作,可以用 RegisterNatives 方法注册 Java native 方法。

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

这样的话,提前建立 Java native 方法和本地 C++ 方法的关系,在调用 Java native 方法的时候无需再查找并建立关系,就会比较快。

例子:

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) {

    // 要注册的 java 类的路径(完整的包名和类名)
    const char *className = "com/teletian/sample/MainActivity";

    /*
     * 要注册的函数列表
     * 参数:
     * 1. java 中用 native 关键字声明的函数名
     * 2. 函数签名,格式:(参数类型)返回类型
     * 3. C/C++ 中对应函数的函数名(地址)
     * */
    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]);
    //注册函数 参数:java 类名,要注册的函数数组,要注册函数的数量
    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;
}

缺点:

  • 代码不够简洁
  • 阅读代码不方便,本地 C++ 方法和 Java native 方法无法互相跳转查看。

优点:

  • 流程清洗可控
  • 效率高。提前建立关系,首次调用方法时速度快
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值