安卓JNI实战教程(一)

  JNI 全称为Java Native Interface 即Java本地接口,JNI是Java调用Native 语言的一种特性。通过JNI可以让Java与C/C++相互调用。

一、如何使用JNI(注:本文中均只介绍CMakeList方式编译):

首先我们要在java中声明一个本地方法如:(此为kotlin 写法 java 写法为 public native void init();)

然后我们需要再c或C++文件中实现

     1 .静态注册方式:

安卓JNI实战教程(一)_第1张图片

              静态注册方式方面的命名必须严格按照命名规则命名 为 JAVA_包名(包名用_分隔)_类名_方法名(JNIEnv *env,jobject mjobject,其他参数..)。

JNIEnv是当前Java线程的执行环境,一个JVM对应一个JavaVM结构,而一个JVM中可能创建多个Java线程,每个线程对应一个JNIEnv结构,它们保存在线程本地存储TLS中。因此,不同的线程的JNIEnv是不同,也不能相互共享使用。JNIEnv结构也是一个函数表,在本地代码中通过JNIEnv的函数表来操作Java数据或者调用Java方法。也就是说,只有在本地代码中拿到了JNIEnv结构,才在本地代码中调用Java代码。jobject 是对应的是java的对象类型 在该方法中表示的是调用该本地方法的对象

   2动态注册方式

当我们使用System.loadLibarary()方法加载so库的时候,Java虚拟机就会找到这个JNI_OnLoad函数并调用该函数。所以我们可以在该函数中注册去动态的注册函数。先看代码

安卓JNI实战教程(一)_第2张图片

安卓JNI实战教程(一)_第3张图片

首先我们通过getEnv() 获取到 JNIEnv结构体指针再看jniRegisterNativeMethods()方法

先是调用了FindClass( className)  获取需要关联对象的jclass(对应java 的class)

然后调用RegisterNatives(clazz, gJni_Methods_table, numMethods) 方法  参数clazz为关联对象的 参数jclass gJni_Methods_table 为JNINativeMethod 的结构体数组   numMethods为   jclass gJni_Methods_table 的大小(方法的个数)

在这里我们要介绍下JNINativeMethod结构体, JNINativeMethod是一个在jni中定义的结构体用于描述native函数与java 函数的关系 安卓JNI实战教程(一)_第4张图片数组中有三个参数 其中name为 java 层的方法名; signature 为函数表示(有参数和返回值组成的字符串,篇幅有限这就不在这展开说了) ;fnPtr为native方法的方法指针。

编写CMakeList文件

安卓JNI实战教程(一)_第5张图片

到此处我们便可以在java成中调用native方法了。

二、在通过JNI在native方法中调用java方法

     1、  先要在native方法中调用java方法必须要先拿到该方法的id 获取方法id的方法为GetMethodID如

安卓JNI实战教程(一)_第6张图片

 第一个参数: jClass为 方法所在的类的jclass对象 如例中就相当MainAcitivy.class ;

第二个参数: 为方法名 

 第三个参数:为有参数和返回值组成的函数签名

2 调用使用

CallVoidMethod

安卓JNI实战教程(一)_第7张图片

    第一个参数为 :     jobject (本例中相当于MainAcitivty的实例对象)

第二个参数为:jmethodID

第三个为参数 :对应参数(如有不止一个参数则在后面继续跟)


至此完成Java 与 native的互相调用 
 

你可能感兴趣的:(android,android,jni,ndk)