一、前言
我们在学习完AndroidStudio NDK环境3中搭建方式和Android NDK构建系统后,已经明白了如何创建一个简单的Android NDK工程。本篇博客将以前两篇为基础,更深入的了解NDK开发。学习如何通过JNI技术实现Java代码与Native代码的通信;
二、知识点概述
对于开发者来讲,我们所有的工作都是围绕着数据。不同的数据有不同的数据类型。Java以及C两种语言规定的数据类型会有区别,我们如何通过Java端传给C端合法的数据类型呢?JNI起到了一个中间转换的作用,通过JNI我们可以方便的实现Java代码与Native代码的通信,无任何障碍。也就是说当我们想通过Java端调用C代码时,其实是Java端调用JNI,JNI再去调用C代码。当我们通过C代码调用java端代码是也是通过C调用JNI,通过jni实现与Java端的通信。
知识点:
- 操作基本数据类型
- 操作字符串
- 操作数组
- 操作类
- 回调Java静态方法/实例方法
- 回调Java静态域/实例域
三、知识点详解
在Java中有两种数据类型:基本数据类型、引用类型。
- 基本数据类型:字节型(int)、字符型(byte)、短整型(short)、整型(int)、长整型(long)、浮点型(float)、双精度型(double)、布尔型(bool)。
- 引用类型:字符串类型(String)、数组([ ])、类(Class);
下面我们进一步了解不同的数据类型在Java与Native之间的通信。
操作基本数据类型
基本数据类型对开发人员来说是透明的;也就是说基本数据类型可以不必使用jni中定义的数据类型来进行转换,可以直接与C/C++的相应基本数据类型进行映射;
如图:
下面这个例子Java端向Native传递基本数据类型的数据:
1.Native有个c函数保存一张图片的信息(width,height,isJpeg,size)
void initPictureInfo(int width, int height , bool isJpeg, long fileSize){
......
}
2.java端通过jni调用c函数。
JNIEXPORT void JNICALL Java_example_zhangjunling_com_ndk_1hellowork_HelloWordJniActivity_initPictureInfo
(JNIEnv *env, jobject obj, jint width, jint height, jboolean isJpeg, jlong fileSize){
//直接调用c代码。这里基本数据类型不需要转换成jni类型,基本数据类型可以直接与C/C++进行映射。
initPictureInfo(width,height,isJpeg,fileSize);
}
操作引用类型
与基本数据类型不同,引用数据类型对开发人员来说是不透明的;也就是说引用数据类型不能直接与C/C++的相应基本数据类型进行映射,必须经过jni层的转换。
下图表示了Java引用类型----->Jni层的转化。
1、把Java字符串传给C/C++
前文已经介绍了字符串属于引用数据类型,在C/C++中不能直接使用Java端String类型的数据。为了在C/C++中可以使用,Jni提供了将Java字符串转成C字符串的方法。GetStringChars函数可以将Unicode格式的Java字符串转换成C/C++字符串;GetStringUTFChars函数可以将UTF-8格式的Java字符串成C/C++字符串。
jboolean isCopy;
const char* javaData = env->GetStringUTFChars(data,&isCopy);
第二个参数,它让调用者确定返回的C字符串地址指向副本还是指向堆中的固定对象。
2、把C/