JNI动态注册

发布于:2024-10-12 ⋅ 阅读:(15) ⋅ 点赞:(0)

静态注册和动态注册的区别

静态注册

  • 命名规则:
    通常是 Java_ 前缀 + Java 类的全限定名 + 方法名。
  • 注册时机:
    在 JVM 启动加载类时自动完成注册,Java 类中的本地方法直接通过函数名绑定。
  • 注册函数的控制:
    JVM 自动处理

动态注册

  • 命名规则:
    动态注册通过手动调用 JNI 提供的 RegisterNatives 方法将 Java 方法与本地函数绑定。
    不需要遵守特定的命名规则,开发者可以灵活地使用任意名称的 C/C++ 函数,然后在程序启动时(通常在 JNI_OnLoad 函数中)进行注册。

  • 注册时机:
    注册时机由开发者控制,通常在 JNI_OnLoad 函数中调用 RegisterNatives 完成注册。

  • 注册函数的控制:
    手动注册,开发者可以完全控制。

JNINativeMethod结构体

typedef struct {
    const char* name;         // native方法名
    const char* signature;    // 方法签名,例如()Ljava/lang/String;
    void*       fnPtr;        // 函数指针
} JNINativeMethod;

方法签名

  字符串,由一对小括号和若干签名符号组成,其中括号内写传入参数的签名符号,没有参数则不写,括号外写返回参数的签名符号。

签名符号 C/C++ java
V void void
Z jboolean boolean
I jnit int
D jdouble double
F jfloat float
B jbyte byte
C jchar char
S jshort short
[Z jbooleanAray boolean[]
[I jintArray int[]
[D jdoubleArray double[]
[F jfloatArray float[]
[B jbyteArray byte[]
[C jcharArray char[]
[S jshortArray short[]
L+完整包名+类名 jobject class

修改native代码

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


jstring myFunc(
        JNIEnv *env, jclass thiz,jint i_param){
        std::string retVal = "参数是===>:";
        retVal+=i_param;
    return env->NewStringUTF(retVal.c_str());
}

JNI函数注册(动态注册)

jint JNI_OnLoad(JavaVM* vm,void* reserved){
    JNIEnv *env = NULL;
    if(vm->GetEnv((void**)&env,JNI_VERSION_1_6)!=JNI_OK){
        return -1;
    }
    jclass clazz = env->FindClass("com/example/ndktest/MainActivity");
    JNINativeMethod methods[] = {
            {"stringFromJNI","()Ljava/lang/String;", (void*)stringFromJNI},
            {"myFunc", "(I)Ljava/lang/String;", (void*)myFunc}
    };

    env->RegisterNatives(clazz,methods,sizeof(methods)/sizeof (methods[0]));
    return JNI_VERSION_1_6;
}

JNI函数调用(动态注册)

		Toast.makeText(this,myFunc(97),Toast.LENGTH_SHORT).show();

        TextView tv = binding.sampleText;
        tv.setText(stringFromJNI());