JNI把Java数组当作引用类型来处理,JNI提供了必要的函数来访问和处理Java数组。

下面一个一个来看。


1.创建数组
我们可以使用NewArray函数在原生代码中创建数组实例,其中可以是Int、Char、和Boolean等,例如NewIntArray,使用这些函数时应该以参数的形式给出数组的大小。看下面一段代码:

先定义一个jintArray数组,然后定义一个jint数组,将jint数组的内容提交给jintArray,然后返回jintArray。

jintArray Java_com_example_jni_MainActivity_getIntArray(JNIEnv* env,jobject thiz) {jintArray javaArray;jint nativeArr[3] = {21,22,23};javaArray = (*env)->NewIntArray(env,3);(*env)->SetIntArrayRegion(env,javaArray,0,3,nativeArr);return javaArray;
}

与NewString函数一样,在内存溢出的情况下,NewArray函数将返回NULL以通知原生代码虚拟机中有异常抛出,这样原生代码就会停止运行。


2.访问数组元素
JNI提供两种访问Java数组元素的方法,可以将Java数组复制为C数组,或者让JNI提供直接指向数组元素的指针。下面将对这两种方法分别介绍。

2.1对副本的操作
我们可以将一个Java数组复制成一个C数组,然后对这个数组进行操作。
看下面一段代码,Java传进来一个数组,我们计算数组元素之和然后返回。

jint Java_com_example_jni_MainActivity_getSum(JNIEnv* env,jobject thiz,jintArray javaArray) {//获得Java传递进来数组的长度jsize length = (*env)->GetArrayLength(env,javaArray);//定义一个C数组jint nativeArr[length];jint sum = 0;//将Java数组区复制到C数组中(*env)->GetIntArrayRegion(env,javaArray,0,length,nativeArr);int i;//求和for(i=0;i<length;i++){sum+=nativeArr[i];}return sum;
}

原生代码可以像使用普通的C数组一样使用和修改数组元素。当原生代码相将所做的修改提交给Java数组时,可以使用SetArrayRegion函数将C数组复制回Java数组中。
看下面代码,我们将Java传进来的数组中的每个元素加1,然后再把修改后的数组返回。

jintArray Java_com_example_jni_MainActivity_arrAdd1(JNIEnv* env,jobject thiz,jintArray javaArray) {//获得Java传递进来数组的长度jsize length = (*env)->GetArrayLength(env,javaArray);//定义一个C数组//将Java数组区复制到C数组中jint nativeArr[length];(*env)->GetIntArrayRegion(env,javaArray,0,length,nativeArr);int i;//修改元素的值for(i=0;i<length;i++){nativeArr[i]=nativeArr[i]+1;}//从C数组向Java数组提交所做的修改(*env)->SetIntArrayRegion(env,javaArray,0,length,nativeArr);return javaArray;
}

2.2对直接指针的操作

原生代码可以用GetArrayElements函数获取指向数组元素的直接指针。第三个参数和我们在上篇博文中提到的一样,它是一个可选参数,该可选参数的名称为isCopy,让调用者确定返回的C字符串地址指向副本还是指向堆中的固定对象。

因为可以像普通的C数组一样访问和处理数组元素,因此JNI没有提供访问和处理元素的方法,JNI要求原生代码用完这些指针必须立刻释放,否则会出现内存溢出问题,原生代码可以使用JNI提供的ReleaseArrayElements函数来释放GetArrayElements函数返回的C数组。该函数有四个参数,第四个是释放模式,有以下三种。

0:将内容复制回来并释放原生数组
JNI_COMMIT:将内容复制回来但是不释放原生数组,一般用于周期性的更新一个Java数组。
JNI_ABORT释放原生数组但是不将内容复制回来。

这次我们用C做个简单的乘法,Java传进来一个数组,对该数组中元素求积之后返回。

jint Java_com_example_jni_MainActivity_multiplication(JNIEnv* env,jobject thiz,jintArray javaArray){jint* nativeDirectArray;jboolean isCopy;jint result = 1;jsize length = (*env)->GetArrayLength(env,javaArray);nativeDirectArray = (*env)->GetIntArrayElements(env,javaArray,&isCopy);int i = 0;for(i=0;i<length;i++){result *= nativeDirectArray[i];}(*env)->ReleaseIntArrayElements(env,javaArray,nativeDirectArray,0);return result;
}

好了,关于数组操作就说这么多,有问题欢迎留言讨论。


版权声明:本文为博主原创文章,未经博主允许不得转载。若有错误地方,还望批评指正,不胜感激。

转载于:https://www.cnblogs.com/lenve/p/4889326.html

NDK开发之数组操作相关推荐

  1. NDK开发 - C/C++ 访问 Java 变量和方法

    上一篇有提到 JNI 访问引用数组,涉及了 C/C++ 访问 Java 实例的方法和变量.虽然在之前的开发中,并没有用到 C/C++ 范围 Java 层数据,但是这部分内容还是很有用的. 传送门:ND ...

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

    文章目录 I . C/C++ 中的 Java 字符串数组类型 II . 获取字符串数组长度 III . 获取字符串数组元素 IV . 类型强转 ( jobject -> jstring ) V ...

  3. 016 Android之NDK开发

    文章目录 NDK入门指南 下载NDK和工具 NDK工程说明 JNI数据类型 JNI中的描述符 JNI基本使用 JAVA代码调用C++代码 C++代码调用JAVA代码 C++代码修改JAVA字段 动态注 ...

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

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

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

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

  6. android ndk怎样加载o文件_JNI初探之NDK 开发环境配置

    安装 CMake.LLDB与NDK 开发工具包 CMake 简介 CMake 是一款比make更强大的编译自动配置工具,它可以根据不同平台.不同的编译器,并通过CMakeLists.txt文件中简单的 ...

  7. 【Android NDK 开发】NDK 交叉编译 ( Ubuntu 中交叉编译动态库 | Android Studio 中配置使用第三方动态库 )

    文章目录 I . 动态库 与 静态库 II . 编译动态库 III. Android Studio 使用第三方动态库 IV . Android Studio 关键代码 V . 博客资源 I . 动态库 ...

  8. android studio下的NDK开发详解

    点击右边,选择你解压的NDK,点击应用.这一步将工具包关联到android  studio. 在 local.properties 文件中设置ndk的路径: 就是你解压的NDK工具集的路径  我的是  ...

  9. Android之NDK开发

    一.NDK产生的背景 Android平台从诞生起,就已经支持C.C++开发.众所周知,Android的SDK基于Java实现,这意味着基于Android SDK进行开发的第三方应用都必须使用Java语 ...

  10. Android之NDK开发学习总结

    Android之NDK开发 http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html 一.NDK产生的背景 Android平台 ...

最新文章

  1. Linux数组计算平均值,从数组中读取并计算平均值
  2. echarts X轴 或者 Y轴 添加标识线
  3. loadrunner- winsock 函数总结
  4. 解决ExcuteFile执行命令时出现“无效字符”的问题
  5. 玹疯:这些年我走过的弯路
  6. UOJ - #117. 欧拉回路(模板)
  7. Java的MD5加密和解密
  8. LeetCode 1926. 迷宫中离入口最近的出口(BFS)
  9. Elasticsearch7.15.2 修改IK分词器源码实现基于MySql8的词库热更新
  10. CSS3 Flex 弹性布局用法详解
  11. 部分 I. 教程_第 2 章 SQL语言_2.2. 概念
  12. 联想面试智力题,听说前面三道题必考(有部份解答)
  13. [C++] - 创建对象时 () 和 {} 的区别
  14. MySql数据库基本语句
  15. 计算机上的字体太小怎么办,电脑字体太小怎么调 电脑字体调整方法有哪些
  16. 漫反射(diffuse reflection)
  17. pycharm占用c盘
  18. 【技法操作】UI界面设计,用PS绘制闹钟页面教程
  19. C# 大地测量高斯投影正反算公式计算程序
  20. 根据经纬度调用Google地图显示对应位置

热门文章

  1. Android-EventBus 使用以及区别
  2. 《深入理解JVM》读书笔记
  3. Centos 7 安装 java、搭建 Jenkins
  4. Linq To EF (添加记录后获取添加的自增ID和叫“ID”的列不是自增列不让插入的问题)...
  5. (转) windows 下ORA-12514:TNS 监听问题
  6. void android.os.Bundle.putBoolean(java.lang.String
  7. Debian系、红帽系、Arch Linux系如何选择安装包
  8. [AutoSar]开发工具 Vector系列和EB系列
  9. Anaconda3环境path与notepad++的NppExec插件激活环境与快速运行python脚本与matlab脚本,c代码
  10. 4月4日 逻辑回归(Logistic Regression-LR)与SVM