I . jintArray 类型说明
1 . C ++ 环境类型定义 : 下面是 jintArray 类型的定义 , jintArray 的本质是一个 _jobject 类对象指针 ;
class _jobject {}; // 定义 _jobject 类 , 这是一个空类 class _jarray : public _jobject {}; // 定义 _jarray 类 继承 _jobject 类 class _jintArray : public _jarray {}; // 定义 _jintArray 类 , 继承 _jarray 类 typedef _jintArray* jintArray; // 定义 _jintArray* 别名 , jintArray
public 继承 : 父类成员在子类中访问级别不变
2 . jintArray 类型本质 : jintArray 是一个 _jintArray 类的指针 , 其 _jintArray 类 对象存储在内存中 , _jintArray * 指针指向该内存 ;
为 _jintArray * 指针变量类型 定义别名 jintArray 类型 ;
3 . ( jintArray -> jint * ) 类型转换 : 这是 Java 中的 int 数组的内存地址 , 如果要在 C/C++ 环境中使用 , 要将该 jintArray 类型变量转为 jint* 类型的变量 ;
使用 jint* GetIntArrayElements(jintArray array, jboolean* isCopy) 方法 , 可以实现上述转化 ( jintArray -> jint * ) ;
II . jboolean 类型说明
1 . C ++ 环境类型定义 : 下面是 jboolean 类型的定义 , jboolean 本质是 无符号 char 类型 ;
typedef unsigned char __uint8_t; // 定义 char 类型别名 __uint8_t typedef __uint8_t uint8_t; // 定义 __uint8_t 类型别名 uint8_t typedef uint8_t jboolean; // 定义 uint8_t 类型别名 jboolean
2 . jboolean 类型取值 : jboolean 的取值只能是 0 和 1 , 也可以使用 JNI_FALSE 和 JNI_TRUE 宏定义 ;
#define JNI_FALSE 0 #define JNI_TRUE 1
III . GetIntArrayElements 方法解析 ( jintArray -> jint* | int* )
1 . GetIntArrayElements 函数作用 : 将 Java 环境的 int 数组类型变量 ( jintArray 类型 ) , 转为 C/C++ 环境中的 jint 数组指针 , 返回一个指针指向 jint 数组首元素地址 ;
jint 本质就是 int 类型 , GetIntArrayElements 函数作用就是将 jintArray 转为 int* 指针 ;
2 . GetIntArrayElements 函数原型 :
struct _JNIEnv { /* _JNIEnv 结构体中封装了 JNINativeInterface 结构体指针 */ const struct JNINativeInterface* functions; ... jint* GetIntArrayElements(jintArray array, jboolean* isCopy) { // 调用 JNINativeInterface 结构体中封装的 GetIntArrayElements 方法 return functions->GetIntArrayElements(this, array, isCopy); } ... }
3 . jintArray array 参数 : 该参数是从 Java 层调用传入的参数 , jintArray 的本质是一个 _jobject 类对象指针 ;
4 . jboolean* isCopy 参数 : 该参数用于指定将 jintArray 类型的变量 , 转为 jint * 指针类型的变量 , 新的指针变量的生成方式 ;
① 将 该参数设置成指向 JNI_TRUE 的指针 : 将 int 数组数据拷贝到一个新的内存空间中 , 并将该内存空间首地址返回 ;
② 将 该参数设置成指向 JNI_FALSE 的指针 : 直接使用 java 中的 int 数组地址 , 返回 java 中的 int 数组的首地址 ;
③ 将 该参数设置成 NULL ( 推荐 ) : 表示不关心如何实现 , 让系统自动选择指针生成方式 , 一般情况下都不关心该生成方式 ;
5 . 代码示例 :
① jboolean* isCopy 参数 准备 代码示例 : jboolean 类型变量可取值 JNI_FALSE 0 和 JNI_TRUE 1 两个值 ;
jboolean isCopy = JNI_TRUE;
② GetIntArrayElements 方法调用代码示例 :
intArray_ 是 Java 层传入的 jintArray intArray_ 参数变量 ;
JNIEnv *env 是 JNI 方法的默认参数 , 这里是 C++ 环境中的 JNIEnv 指针类型 ;
jboolean* isCopy 设置成 NULL 参数表示 不关心 jint* 类型变量的生成方式 ;
jint *intArray = env->GetIntArrayElements(intArray_, NULL);
如果是其它基础数据类型的数组 , 将 Get***ArrayElements 方法名中的 基础数据类型修改一下即可 ;
如果是布尔类型的数组 , 使用 GetBooleanArrayElements 方法 ;
如果是浮点型的数组 , 使用 GetFloatArrayElements 方法 ;
如果是字符型的数组 , 使用 GetCharArrayElements 方法 ;
IV . jarray 类型说明
1 . jarray 类型 : 该类型的本质是一个指针 , 指向一个空对象地址 , 这个对象一般是从 Java 层传递进来 ;
class _jobject {}; // 定义 _jobject 空类 class _jarray : public _jobject {}; // 定义 _jarray 类 , 继承 _jobject 类 typedef _jarray* jarray; // 定义 _jarray* 指针类型 别名为 jarray
2 . _jarray 类子类 : 下面定义的 9 个类 , 都是 _jarray 子类 , 都可以使用 GetArrayLength 方法获取数组长度 ;
class _jarray : public _jobject {}; //下面定义的都是 jarray 子类 class _jobjectArray : public _jarray {}; class _jbooleanArray : public _jarray {}; class _jbyteArray : public _jarray {}; class _jcharArray : public _jarray {}; class _jshortArray : public _jarray {}; class _jintArray : public _jarray {}; class _jlongArray : public _jarray {}; class _jfloatArray : public _jarray {}; class _jdoubleArray : public _jarray {};
3 . Java 传入的数组类型别名 : 下面定义的 9 个别名 , 本质上都是 _jarray 类型对象 或者 其子类对象的 指针 , 即 _jarray* 类型 ;
typedef _jarray* jarray; //下面是 9 个是 Java 传入的数组类型别名 typedef _jobjectArray* jobjectArray; typedef _jbooleanArray* jbooleanArray; typedef _jbyteArray* jbyteArray; typedef _jcharArray* jcharArray; typedef _jshortArray* jshortArray; typedef _jintArray* jintArray; typedef _jlongArray* jlongArray; typedef _jfloatArray* jfloatArray; typedef _jdoubleArray* jdoubleArray;
V . GetArrayLength 方法解析 ( 获取 jarray 数组长度 )
1 . 函数作用 : 获取 jarray 数组长度 , 该 jarray 类型可以是下面定义的类型 ;
typedef _jarray* jarray; //下面是 9 个是 Java 传入的数组类型别名 typedef _jobjectArray* jobjectArray; typedef _jbooleanArray* jbooleanArray; typedef _jbyteArray* jbyteArray; typedef _jcharArray* jcharArray; typedef _jshortArray* jshortArray; typedef _jintArray* jintArray; typedef _jlongArray* jlongArray; typedef _jfloatArray* jfloatArray; typedef _jdoubleArray* jdoubleArray;
2 . 函数原型 :
struct _JNIEnv { /* _JNIEnv 结构体中封装了 JNINativeInterface 结构体指针 */ const struct JNINativeInterface* functions; ... jsize GetArrayLength(jarray array) { 调用 JNINativeInterface 结构体中封装的 GetArrayLength 方法 return functions->GetArrayLength(this, array); } ... }
3 . 返回值类型说明 : jsize 类型本质还是 int 类型 ;
typedef int __int32_t; typedef __int32_t int32_t; typedef int32_t jint; typedef jint jsize;
4 . 函数调用示例 : 其中的 jintArray intArray_ 是 Java 层传入的参数 ;
jsize len = env->GetArrayLength(intArray_);
VI . 日志打印
1 . 日志库配置 :
① 导入日志库 : #include <android/log.h>
② CMake 设置日志库 : add_library 设置动态库名称 , find_library 中为 查找日志库 ,
target_link_libraries 连接日志库 ; add_library( native-lib SHARED native-lib.cpp) find_library( log-lib log) target_link_libraries( native-lib ${log-lib})
2 . 日志打印函数函数原型 :
int __android_log_print(int prio, const char* tag, const char* fmt, ...)
3 . 日志打印函数参数说明 :
① int prio 参数 : 日志的等级 , 定义在 log.h 的 android_LogPriority 枚举中 ;
ANDROID_LOG_VERBOSE ANDROID_LOG_DEBUG ANDROID_LOG_INFO ANDROID_LOG_WARN ANDROID_LOG_ERROR
② const char* tag 参数 : 日志打印的 TAG 标签 , 这是一个 C/C++ char* 类型字符串 ;
③ const char* fmt, … 参数 : 可变参数 ;
4 . 日志打印函数代码示例 :
/* __android_log_print 打印 Android 日志函数 函数原型 : int __android_log_print(int prio, const char* tag, const char* fmt, ...) int prio 参数 : 日志的等级 , 定义在 jni.h 的 android_LogPriority 枚举中 ANDROID_LOG_VERBOSE ANDROID_LOG_DEBUG ANDROID_LOG_INFO ANDROID_LOG_WARN ANDROID_LOG_ERROR const char* tag 参数 : 日志打印的 TAG 标签 , 这是一个 C/C++ char* 类型字符串 const char* fmt, ... 参数 : 可变参数 */ __android_log_print(ANDROID_LOG_INFO, "JNI_TAG" , "%d . %d" , i , *num);
VII . 遍历 int 数组
1 . 使用指针遍历 jint 数组 : jint *intArray ;
intArray 是数组首元素地址
intArray + 1 是第 1 个元素的首地址
intArray + k 是第 k 个元素的首地址
2 . 函数调用 代码示例 :
/* 使用指针进行访问 intArray 是数组首元素地址 intArray + 1 是第 1 个元素的首地址 intArray + k 是第 k 个元素的首地址 使用 *(intArray + k) 可以获取第 k 个元素的值 */ for(int i = 0; i < len; i ++){ //获取第 i 个元素的首地址 , 使用 *num 可以获取第 i 个元素的值 int *num = intArray + i; /* __android_log_print 打印 Android 日志函数 函数原型 : int __android_log_print(int prio, const char* tag, const char* fmt, ...) int prio 参数 : 日志的等级 , 定义在 jni.h 的 android_LogPriority 枚举中 ANDROID_LOG_VERBOSE ANDROID_LOG_DEBUG ANDROID_LOG_INFO ANDROID_LOG_WARN ANDROID_LOG_ERROR const char* tag 参数 : 日志打印的 TAG 标签 , 这是一个 C/C++ char* 类型字符串 const char* fmt, ... 参数 : 可变参数 */ __android_log_print(ANDROID_LOG_INFO, "JNI_TAG" , "%d . %d" , i , *num); //修改数组中的值 *num = 8888; }