文章目录

  • I . C/C++ 中的 Java 字符串数组类型
  • II . 获取字符串数组长度
  • III . 获取字符串数组元素
  • IV . 类型强转 ( jobject -> jstring )
  • V . 字符串转换 ( jstring -> char* )
  • VI . 字符串释放
  • VII . 部分代码示例

I . C/C++ 中的 Java 字符串数组类型


JNI 中 C/C++ 代码里的 Java 字符串数组类型 : jobjectArray ;

① JNI 类型现状 : 在 JNI 中没有定义 Java 字符串数组类型 , 只定义了 Java 字符串类型 jstring ;

② Object 对应 jobject : 在 C/C++ 环境中 jobject 类型对应 Java 中的 Object 类型 , Java 中字符串也是 Object 类型的 ;

③ 字符串数组类型 : 因此在 C/C++ 环境中使用 对象数组 jobjectArray 来当做 字符串数组类型 ;

II . 获取字符串数组长度


1 . 前提条件 : Java 层传入参数 jobjectArray stringArray , 该参数对应 Java 代码中的 String[] stringArray 参数 ;

下面的 GetArrayLength 方法的 stringArray 参数 , 就是 jobjectArray 类型的 ;

2 . 获取字符串数组长度 代码示例 : 其中返回值 jsize 是 int 类型的别名 ;

jsize stringArrayLength = env->GetArrayLength(stringArray);

GetArrayLength 方法详细解析参考如下内容 :
GetArrayLength 方法解析 ( 获取 jarray 数组长度 )

III . 获取字符串数组元素


C/C++ 代码中获取指定索引的 Java 字符串数组类型的元素 ;

1 . 调用方法 : 调用 JNIEnv * env 的 GetObjectArrayElement 方法 , 可以获取指定索引的 jobject 引用类型变量 ;

2 . 方法原型 :

struct _JNIEnv {/* _JNIEnv  结构体中封装了 JNINativeInterface 结构体指针 */const struct JNINativeInterface* functions;...// 最终 调用的 还是 JNINativeInterface 结构体中封装的 GetObjectArrayElement方法jobject GetObjectArrayElement(jobjectArray array, jsize index){ return functions->GetObjectArrayElement(this, array, index); }...
}

3 . GetObjectArrayElement 参数说明 :

① jobjectArray array 参数 : 由 Java 层传入的 Java 对象数组 ;

② jsize index 参数 : 要获取的数组元素的索引值 ;

4 . 获取对象数组指定元素代码示例 :

其中的参数 stringArray 是 jobjectArray 类型的 , 由 JNI 方法传入 ;

其中的参数 i 是 int 类型的 , 是要获取的元素的索引值 , 从 0 开始计数 ;

jobject string_object = env->GetObjectArrayElement(stringArray, i);

IV . 类型强转 ( jobject -> jstring )


将 jobject 转为 jstring 类型 : string_object 是 jobject 类型变量 ;

        // 2.2 将 jobject 类型强转成 jstring 类型 , 这两个都代表了 Java 的数据类型jstring string_java = static_cast<jstring>(string_object);

详细内容参考下面博客 :
【C++ 语言】类型转换 ( 转换操作符 | const_cast | static_cast | dynamic_cast | reinterpret_cast | 字符串转换 )

V . 字符串转换 ( jstring -> char* )


1 . GetStringUTFChars 方法 : 将 jstring 类型字符串 ( Java 中的字符串 ) 转为 char* 类型字符串 ( C/C++ 中的字符串 ) ;

2 . 函数原型 : jstring string 参数是 Java 通过 JNI 传入的 , 代表 Java 字符串 ;

struct _JNIEnv {/* _JNIEnv  结构体中封装了 JNINativeInterface 结构体指针 */const struct JNINativeInterface* functions;...// 最终 调用的 还是 JNINativeInterface 结构体中封装的 GetStringUTFChars 方法const char* GetStringUTFChars(jstring string, jboolean* isCopy){ return functions->GetStringUTFChars(this, string, isCopy); }...
}

3 . jboolean* isCopy 参数 : 该参数用于指定将 jintArray 类型的变量 , 转为 jint * 指针类型的变量 , 新的指针变量的生成方式 ;

① 将 该参数设置成指向 JNI_TRUE 的指针 : 将 int 数组数据拷贝到一个新的内存空间中 , 并将该内存空间首地址返回 ;

② 将 该参数设置成指向 JNI_FALSE 的指针 : 直接使用 java 中的 int 数组地址 , 返回 java 中的 int 数组的首地址 ;

③ 将 该参数设置成 NULL ( 推荐 ) : 表示不关心如何实现 , 让系统自动选择指针生成方式 , 一般情况下都不关心该生成方式 ;

④ jboolean 类型取值 : jboolean 的取值只能是 0 和 1 , 也可以使用 JNI_FALSE 和 JNI_TRUE 宏定义 ;

#define JNI_FALSE 0
#define JNI_TRUE 1

4 . jstring 字符串转换 为 char* 字符串示例 :

const char *string_c = env->GetStringUTFChars(string_java, JNI_FALSE);

VI . 字符串释放


1 . ReleaseStringUTFChars 方法 : 将 Java 字符串 和 C/C++ 字符串都释放 ;

2 . 函数原型 :

jstring string 参数是 Java 通过 JNI 传入的 , 代表 Java 字符串 ;

const char* utf 参数是通过 GetStringUTFChars 方法将上面的 Java 字符串转成的 C/C++ 字符串 ;

struct _JNIEnv {/* _JNIEnv  结构体中封装了 JNINativeInterface 结构体指针 */const struct JNINativeInterface* functions;...// 最终 调用的 还是 JNINativeInterface 结构体中封装的 ReleaseStringUTFChars 方法void ReleaseStringUTFChars(jstring string, const char* utf){ functions->ReleaseStringUTFChars(this, string, utf); }...
}

VII . 部分代码示例


部分代码示例 :

#include <jni.h>
#include <string>//导入日志库
#include <android/log.h>//定义日志宏 , 其中的 __VA_ARGS__ 表示可变参数
#define  LOGE(...) __android_log_print(ANDROID_LOG_ERROR,"JNI",__VA_ARGS__);...extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_jni_MainActivity_jniArrayTest(JNIEnv *env, jobject instance, jintArray intArray_,jobjectArray stringArray) {...// II . 引用类型数组操作 ( 获取字符串数组 )// 1 . 获取字符串数组长度jsize stringArrayLength = env->GetArrayLength(stringArray);// 2 . 遍历字符串数组for(int i = 0; i < stringArrayLength; i ++) {/*2.1 获取 jobject 数组中第 i 个元素注意 : 获取的是 jobject 类型变量函数原型 : jobject GetObjectArrayElement(jobjectArray array, jsize index)jobjectArray array 参数 : 是 Java 层传入的 Java 对象数组 参数 , 即 Native 层的调用函数的参数jsize index 参数 : 对象元素的索引值 , 取值范围 0 ~ stringArrayLength - 1返回值 : 返回的是 jobject 类型的变量*/jobject string_object = env->GetObjectArrayElement(stringArray, i);// 2.2 将 jobject 类型强转成 jstring 类型 , 这两个都代表了 Java 的数据类型jstring string_java = static_cast<jstring>(string_object);/*2.3 将 jstring 类型转为 char* 类型jstring 类型简介 :class _jobject {};class _jstring : public _jobject {};typedef _jstring*       jstring;由上面可见 , jstring 只是 继承了 _jobject 类 , 没有任何实现 , 是一个空类因此需要借助 C/C++ 方法 将 java 类型的 jstring 字符串 其转为 C/C++ 类型的 char* 类型字符串转换函数原型 : void ReleaseStringUTFChars(jstring string, const char* utf)*/const char *string_c = env->GetStringUTFChars(string_java, 0);// 2.4 打印 转换后的 字符串值__android_log_print(ANDROID_LOG_INFO, "JNI_TAG", "打印字符串数组元素 : %d . %s", i, string_c);// 2.5 释放 char* 字符串env->ReleaseStringUTFChars(string_java, string_c);}}

代码执行结果 :

01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印 int 数组元素 : 0 . 1
01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印 int 数组元素 : 1 . 2
01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印 int 数组元素 : 2 . 666
01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印 int 数组元素 : 3 . 888
01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印 int 数组元素 : 4 . 95555
01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印字符串数组元素 : 0 . Hello
01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印字符串数组元素 : 1 . World
01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印字符串数组元素 : 2 . Hanshuliang
01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: Java 层 jniArrayTest 执行完毕后 , int[] intArray 数组内容 : [8888, 8888, 8888, 8888, 8888]

限于篇幅就不再贴完整代码了 , 去下载博客资源有全套的 JNI 文档教程 , 及博客源码

【Android NDK 开发】JNI 方法解析 ( 字符串数组参数传递 | 字符串遍历 | 类型强转 | Java 字符串与 C 字符串转换 | 字符串释放 )相关推荐

  1. 【Android NDK 开发】JNI 方法解析 ( JNIEnv *env 参数 )

    文章目录 一. JNI 方法解析 二. JNIEnv *env 参数解析 三. C 语言 环境中 JNIEnv *env 参数解析 四. C ++ 环境中 JNIEnv *env 参数解析 总结 : ...

  2. Android NDK开发之旅(3): 详解JNI数据类型与C/C++、Java之间的互调

    Android NDK开发之旅(3):详解JNI数据类型与C/C++.Java之间的互调 (码字不易,转载请声明出处:http://blog.csdn.net/andrexpert/article/d ...

  3. Android NDK开发之旅(2):一篇文章搞定Android Studio中使用CMake进行NDK/JNI开发

    Android NDK开发之旅(2):一篇文章搞定android Studio中使用CMake进行NDK/JNI开发 (码字不易,转载请声明出处:http://blog.csdn.NET/andrex ...

  4. 安卓逆向_15( 三 ) --- Android NDK 开发【 jni 静态注册、JNI_OnLoad 动态注册】

    Android Studio开发JNI示例:https://blog.csdn.net/wzhseu/article/details/79683045 JNI_动态注册_静态注册.zip : http ...

  5. Android 高级开发 JNI NDK 介绍与使用

    Android 高级开发 JNI & NDK 介绍与使用 前言 对于没接触过的领域,即是挑战也是机遇,不仅能够提升自己的能力.还能够学习到新的技术知识 而学习新的技术的时候,最好是从头开始按照 ...

  6. OpenCV android sdk配置OpenCV android NDK开发实例

    OpenCV android sdk配置OpenCV android NDK开发实例 [尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article/det ...

  7. 【Android NDK 开发】Android Studio 使用 CMake 导入动态库 ( 构建脚本路径配置 | 指定动态库查找路径 | 链接动态库 )

    文章目录 I . CMake 引入动态库与静态库区别 II . Android Studio 中 CMake 引入动态库流程 III . 指定动态库查找路径 IV . 链接函数库 V . 完整代码示例 ...

  8. 【Android NDK 开发】Android.mk 配置静态库 ( Android Studio 配置静态库 | 配置动态库与静态库区别 | 动态库与静态库打包对比 )

    文章目录 I . Android Studio 中使用 Android.mk 配置静态库 总结 II . 第三方动态库来源 III . 配置 Android.mk 构建脚本路径 IV . 预编译 第三 ...

  9. 【Android NDK 开发】Android.mk 配置动态库 ( Android Studio 配置动态库 | 动态库加载版本限制 | 本章仅做参考推荐使用 CMake 配置动态库 )

    文章目录 I . Android Studio 中使用 Android.mk 配置动态库 总结 II . 第三方动态库来源 III . 配置 Android.mk 构建脚本路径 IV . 预编译 第三 ...

最新文章

  1. 大盘点|6D姿态估计算法汇总(上)
  2. MongoDB 征途
  3. birt脚本for循环_Shell脚本应用 – for、while循环语句
  4. R: ggplot2(1)
  5. P1080 国王游戏(贪心+高精度乘除及大数比较)
  6. SpringCloud Gateway的工作方式
  7. .NET Core 3.0 Preview 3中关于ASP.NET Core的更新内容
  8. 牛客题霸 [有关阶乘的两个问题1] C++题解/答案
  9. Rest风格---ElasticSearch
  10. modemcu 打包_nodemcu固件的烧录及lua开发
  11. Linux下查看网卡实时流量工具
  12. atitit..国富论 在现代it企业项目管理中的作用attialx 总结---国富论读后感 attialx
  13. 大数据处理技术-头歌平台-答案
  14. excel VBA自动化 - 多个工作簿自动合并到一个工作簿
  15. 强化学习王者荣耀项目修改
  16. English—句子
  17. 美国国土安全部2.5万雇员隐私信息遭黑客窃取
  18. Choosing Teams
  19. 什么是响应式编程,Java 如何实现
  20. BadUSB+ProMicro+Arduino做一个插入U盘自动攻击

热门文章

  1. legend3---OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 10054
  2. 尝试create tech team
  3. UNIX环境高级编程 第12章 线程控制
  4. 2017/05/07 java 基础 随笔
  5. 在React 组件中使用Echarts
  6. PHP中IP地址与整型数字互相转换详解
  7. asp.net如何读取Excel文件
  8. swift 如何实现点击view后显示灰色背景
  9. (剑指Offer)面试题10:二进制中1的个数
  10. 制作一个表格,显示班级的学生信息。