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. csu 10月 月赛 J 题

    Description CSU又到了一年中评奖学金的时候了……各大学霸都或多或少地拿到了各种奖学金(你们自己看着办吧). 在这里,评奖学金有个很奇怪的规矩——每个同学得到的奖学金数一定满足相邻的两个非 ...

  2. 【UVA 10369】 Arctic Network (最小生成树)

    [题意] 南极有n个科研站, 要把这些站用卫星或者无线电连接起来,使得任意两个都能直接或者间接相连.任意两个都有安装卫星设备的,都可以直接通过卫星通信,不管它们距离有多远. 而安装有无线电设备的两个站 ...

  3. java WebService简单使用案例

    首先,建立一个WebService: package garfield; import javax.jws.WebService; import javax.xml.ws.Endpoint; @Web ...

  4. ASP.NET多用户操作相同互斥的对象

    [一篮饭特稀原创,转载请注明出自http://www.cnblogs.com/wanghafan/p/3574154.html ] 现象:公有静态变量不可用于ASP.NET多用户操作,否则该变量会被多 ...

  5. redis pub/sub 发布订阅

    Redis的列表数据结构有blpop和brpop命令,能从列表里返回且删除第一个(或最后一个)元素,或者被堵塞,直到有一个元素可供操作.这可以用来实现一个简单的队列.(参考:http://www.cn ...

  6. java 图片文件格式转换(多页tif转jpg 、jpg转tif)

    package util; import java.awt.image.RenderedImage; import java.awt.image.renderable.ParameterBlock; ...

  7. [转]NHibernate之旅(2):第一个NHibernate程序

    本节内容 开始使用NHibernate 1.获取NHibernate 2.建立数据库表 3.创建C#类库项目 4.设计Domain 4-1.设计持久化类 4-2.编写映射文件 5.数据访问层 5-1. ...

  8. jQuery dataTables 网格

    对于服务器来说,可以通过请求参数来获得当前的操作信息. 类型 名称 说明 int iDisplayStart 显示的起始索引 int iDisplayLength 显示的行数 int iColumns ...

  9. C# 4.0 新特性

    http://www.cnblogs.com/webabcd/archive/2010/05/27/1744899.html 在MVC中Controller的action方法 常用的:可选参数和参数默 ...

  10. [转]Angular, Backbone, or Ember: Which is Best for your Build?

    In order to choose which framework is right for your build, we've asked four important questions of ...