JNI:Java调用C接口的方法(1)

JNI基本概念:

  • JNIEnv: Java的本地化环境。C/c++访问Java的对象、类等通过JNIEnv,它里面包含了所有的API。只要和Java交互的都需要它。
  • JavaVM:Java虚拟机。在一个进程里是可以创建很多个虚拟机的。但是对于Android来说,一个进程对应一个VM。每个APP对应一个JavaVM.JavaVM就是来获取JNIEnv的。它有个方法getEnv()。JNIEnv与JavaVM的关系是一个JavaVM里有很多个线程,那么每个线程对应一个JNIEnv。
  • 线程。JNIEnv与线程是一一对应的。在C层去想问Java层,必须是在当前的线程下,获取到当前线程的JNIEnv,才能进行访问。否则在其他的线程里去访问另外一个线程的JNIEnv会导致Crash。

Java去调用C的过程:【以上篇文章创建的DEMO为例子】

用Java去访问C层的接口。

需要在Java层做如下事情:

  • 创建native方法。[native表明了c/c++的接口]

仿写:

JNI:Java调用C接口的方法(1)_第1张图片

JNI:Java调用C接口的方法(1)_第2张图片

鼠标移到yinleiFromJNI上面,会有一个灯泡,可以快速创建C层的代码:

JNI:Java调用C接口的方法(1)_第3张图片

JNIEnv *env, jobject thiz这2个参数。

刚刚介绍了JNIEnv这是我们访问java都可以通过它去访问。

jobject 就是谁调用了这个api,就会把这个java对象当作参数传进来,传进来的时候就是通用类型的object,前面加个j就是jnienv专门为java对象设计的一个类型jobject。

在Java层没有输入任何参数,但是在生成的代码中却包含了上面的2个参数。再看模板JNI:Java调用C接口的方法(1)_第4张图片

模板里也有这2个参数。这2个参数实际就是Java虚拟机在调用c/c++接口的时候传进来的。也就是说,Java的api通过Java调用我们前面标识的native的方法的时候,最终调用的是java虚拟机里的。Java虚拟机最终会将我们的线程环境jnienv以及调用这个方法的java对象传进来。这样在java层就可以做很多事情。有了这个java对象可以调用这个对象所提供的方法或者属性。有了这个jnienv、线程对象就知道我当前是在这个线程里做的,就直接通过env对象去调用这个相应的方法。然后JNI:Java调用C接口的方法(1)_第5张图片通过env调用newStringUTF【Java的一个对象】,并传入了一个yinlei的字符串。它就会把c/c++的一个String转成Java对象返回回去。

  • java层的native方法传入参数的时候:

无论我们传什么,它最终都会转换为jobject。

改写下它:

JNI:Java调用C接口的方法(1)_第6张图片

上述代码通过getStringUtfchars将java层的string转成了char *,拿到char *后就可以做一些操作了。

然后看到上面中的releaseStringUTFChars,是释放相应的资源。【毕竟c/c++中申请指针内存还要释放的嘛】

然后return 返回值。

JNI:Java调用C接口的方法(1)_第7张图片

然后运行查看结果:

JNI:Java调用C接口的方法(1)_第8张图片

ok,符合预想预期。


总结,编写方法时候:

  1. 在java层编写native的api
  2. 在c++层实现该api
  3. c++做相应的逻辑然后返回给java层,java层再做显示

你可能感兴趣的:(Android,JNI)