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;
}

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


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

NDK开发之数组操作的更多相关文章

  1. NDK开发之字符串操作

    在JNI中,Java字符串被当作一个引用来处理.这些引用类型并不像原生C字符串一样可以直接使用,JNI提供了Java字符串与C字符串之间转换的必要函数,因为Java字符串对象是不可变的(如果对这里有异 ...

  2. Android NDK开发篇(五):Java与原生代码通信(数据操作)

    尽管说使用NDK能够提高Android程序的运行效率,可是调用起来还是略微有点麻烦.NDK能够直接使用Java的原生数据类型,而引用类型,由于Java的引用类型的实如今NDK被屏蔽了,所以在NDK使用 ...

  3. Android NDK开发 JNI操作java构造方法,普通方法,静态方法(七)

    Android NDK开发 JNI操作java普通.静态.构造方法 1.Jni实例化一个Java类的实例jobject 1.通过FindClas( ),获取Java类的的jclass 2.通过GetM ...

  4. Android NDK开发篇:Java与原生代码通信(数据操作)

    虽然说使用NDK可以提高Android程序的执行效率,但是调用起来还是稍微有点麻烦.NDK可以直接使用Java的原生数据类型,而引用类型,因为Java的引用类型的实现在NDK被屏蔽了,所以在NDK使用 ...

  5. NDK开发—基础知识实战Demo

    简介 前面写了几篇NDK相关的文章: NDK开发-简介&环境搭建(Eclipse,Android Studio) NDK开发-Android Studio+gradle-experimenta ...

  6. NDK开发-零散知识点整理

    JavaVM 标准Java平台下,每一个Process可以产生很多JavaVM对象,但在Android平台上,每一个Process只能产生一个Dalvik VM对象,也就是说在Android进程中是通 ...

  7. Android NDK开发入门实例

    AndroidNDK是能使Android应用开发者把从c/c++编译而来的本地代码嵌入到应用包中的一系列工具的组合. 注意: AndroidNDK只能用于Android1.5及以上版本中. I. An ...

  8. NDK开发总结

    NDK开发差不多结束了, 估计后面也不会再碰了诶, 想着还是写个总结什么的,以后捡起来也方便哈.既然是总结,我这里就不会谈具体的细节,只会记录下我觉得重要的东西, 所以这篇随笔不是为萌新学习新知识准备 ...

  9. Android NDK 开发(四)java传递数据到C【转】

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/41845701 前面几篇文章介绍了Android NDK开发的简单概念.常见错误及处 ...

随机推荐

  1. BZOJ 1715: [Usaco2006 Dec]Wormholes 虫洞

    Description John在他的农场中闲逛时发现了许多虫洞.虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前).John的每个农场有M条小路(无向边)连接着N ...

  2. WEB SSH之Shellinabox

    用起来方便的,参考URL: http://lzw.me/a/shellinabox.html 生成 pem 证书,可以 https 方式启动.pem 证书的格式为公钥加私钥,并以 x509 的格式进行 ...

  3. SPRING IN ACTION 第4版笔记-第三章Advancing wiring-001-DataSource在应用和开发环境之间切换 profile

    一. DataSource在应用和开发环境的产生方式不同,可以用srping 的profile管理 Spring’s solution for environment-specific beans i ...

  4. GCC优化选项-fomit-frame-pointer对于esp和ebp优化的作用

    我的博客:www.while0.com -fomit-frame-pointer选项是发布产品时经常会用到的优化选项,它可以优化汇编函数中用edp协助获取堆栈中函数参数的部分,不使用edp,而是通过计 ...

  5. 【HDOJ】1983 Kaitou Kid - The Phantom Thief (2)

    不仅仅是DFS,还需要考虑可以走到终点.同时,需要进行预处理.至多封闭点数为起点和终点的非墙壁点的最小值. #include <iostream> #include <cstdio& ...

  6. bzoj2426

    稍微列个式子就知道是贪心 ..] of longint; m,b,h0,n,i,p,j,x,ans,s:longint; procedure swap(var a,b:longint); var c: ...

  7. 计算几何(凸包):SHTSC 2012 信用卡凸包

    这道题是水题,发现平移某些边,答案就是圆心的凸包+一个圆的周长. 不要忽视精度误差! #include <algorithm> #include <iostream> #inc ...

  8. bzoj 1007 [HNOI2008]水平可见直线(单调栈)

    1007: [HNOI2008]水平可见直线 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 5120  Solved: 1899[Submit][Sta ...

  9. JavaScript高级程序设计58.pdf

    15章 使用Canvas绘图 略 16章 HTML5脚本编程 HTML5规范了新的HTML标记和JavaScript API,以便简化创建动态Web界面的工作 跨文档消息传递 简称XDM,指来自不同域 ...

  10. Tyvj P1463 智商问题 分块

    P1463 智商问题 时间: 1500ms / 空间: 131072KiB / Java类名: Main 背景 各种数据结构帝~各种小姊妹帝~各种一遍AC帝~ 来吧! 描述 某个同学又有很多小姊妹了他 ...