JNI函数的2种书写方式

一、静态注册

  • 原理:
  1. 根据函数名来建立 java 方法与 JNI 函数的一一对应关系;
  2. 以Java为前缀,并且用“_”下划线,将包名、类名以及native方法名连接起来;
  • 实现流程:
  1. 编写 java 代码;
  2. 利用 javah 指令生成对应的 c 文件;
  3. 对 c 文件中的声明进行实现;
 public class MainActivity extends AppCompatActivity {
 
     // Used to load the 'native-lib' library on application startup.
     static {
         System.loadLibrary("native-lib");
     }
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();
}

 

 #include <jni.h>
 #include <string>
 
 extern "C" JNIEXPORT jstring JNICALL
 Java_com_example_myapplication_MainActivity_stringFromJNI(
         JNIEnv *env,
         jobject /* this */) {
     std::string hello = "Hello from C++";
     return env->NewStringUTF(hello.c_str());
}

二、动态注册

  • 原理:
  1. 利用 RegisterNatives 方法来注册 java 方法与 JNI 函数的一一对应关系;
  • 实现流程:
  1. 利用结构体 JNINativeMethod 数组记录 java 方法与 JNI 函数的对应关系;
  2. 实现 JNI_OnLoad 方法,在加载动态库后,执行动态注册;
  3. 调用 FindClass 方法,获取 java 对象;
  4. 调用 RegisterNatives 方法,传入 java 对象,以及 JNINativeMethod 数组,以及注册数目完成注册;
 public class JniUtils {
 
     static {
         System.loadLibrary("native-lib");
     }
 
     public static native String stringFromJNI();
 
     public static native int calculateByJNI(int count);
}

 

 #include <jni.h>
 #include <string>
 
 // 指定要注册的类
 #define JNIREG_CLASS "com/example/jnilibrary/JniUtils"
 
 // 指定代码所在的段。在编译时,把该函数编译到自定义的section里。
 // 由于在java层没有定义该函数,因此需要写到一个自定义的section里。
 extern "C"
__attribute__((section(".mysection"))) JNICALL jstring getStr1(JNIEnv *env, jobject obj) {
    return env->NewStringUTF("Hello from C++");
}

extern "C"
__attribute__((section(".mysection"))) JNICALL jint getInt1(JNIEnv *env, jobject obj, jint count) {
    return (count + 1);
}

// 第一个参数:Java层的方法名
// 第二个参数:方法的签名,括号内为参数类型,后面为返回类型
// 第三个参数:需要重新注册的方法名
static JNINativeMethod getMethods[] = {
        {"stringFromJNI",  "()Ljava/lang/String;", (void *) getStr1},
        {"calculateByJNI", "(I)I",                 (void *) getInt1}
};

extern "C"
int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *getMethods,
                          int numMethods) {
    jclass clazz;
    clazz = env->FindClass(className);
    if (clazz == NULL) {
        return JNI_FALSE;
    }
    if (env->RegisterNatives(clazz, getMethods, numMethods) < 0) {
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

extern "C"
int registerNatives(JNIEnv *env) {
    if (!registerNativeMethods(env, JNIREG_CLASS, getMethods,
                               sizeof(getMethods) / sizeof(getMethods[0]))) {
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

extern "C"
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env;
    if (vm->GetEnv((void **) (&env), JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }
    if (!registerNatives(env)) {
        return -1;
    }
    return JNI_VERSION_1_6;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值