JNI在处理基本类型数组和对象数组上面是不同的。对象数组里面是一些指向对象实例或者其它数组的引用。

因为速度的原因,先通过GetXXXArrayElements函数把简单类型的数组转化成本地类型的数组,并返回其数组的指针,然后通过该指针来对拷贝数组进行处理。
对拷贝数组处理完后,通过ReleaseXXXArrayElements函数把修改后的拷贝数组的反射到java数组,

然后释放所有相关的资源。

基本类型数组:

获取数组元素指针的对应关系:
  函数            数组类型
  GetBooleanArrayElements   boolean
   GetByteArrayElements    byte
  GetCharArrayElements     char
  GetShortArrayElements    short
  GetIntArrayElements     int
   GetLongArrayElements    long
  GetFloatArrayElements     float
  GetDoubleArrayElements   double
  
释放数组元素指针的对应关系:
  Function            Array Type
   ReleaseBooleanArrayElements   boolean
   ReleaseByteArrayElements    byte
   ReleaseCharArrayElements    char
   ReleaseShortArrayElements    short
   ReleaseIntArrayElements     int
   ReleaseLongArrayElements    long
   ReleaseFloatArrayElements    float
   ReleaseDoubleArrayElements   double

数组的引用类型是一般是jarray或者jarray的子类型jintArray。就像jstring不是一个C字符串类型一样,jarray也不是一个C数组类型。
所以,不要直接访问 jarray。你必须使用合适的JNI函数来访问基本数组元素:

使用GetIntArrayRegion 函数来把一个 int数组中的所有元素复制到一个C缓冲区中,然后我们在本地代码中通过C缓冲区来访问这些元素。

 JNIEXPORT jint JNICALL  Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)
{
jint buf[10];
jint i, sum = 0;
(*env)->GetIntArrayRegion(env, arr, 0, 10, buf); for (i = 0; i < 10; i++) {
sum += buf[i];
}
return sum;
}

JNI支持一系列的Get/Release<Type>ArrayElement 函数,这些函数允许本地代码获取一个指向基本类型数组的元素的指针。

 JNIEXPORT jint JNICALL  Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)
{
jint *carr;
jint i, sum = 0;
carr = (*env)->GetIntArrayElements(env, arr, NULL); //推荐使用
if (carr == NULL) {
return 0; /* exception occurred */
}
for (i=0; i<10; i++) {
sum += carr[i];
}
(*env)->ReleaseIntArrayElements(env, arr, carr, 0);
return sum;
}

如果你想在一个预先分配的C缓冲区和内存之间交换数据,应该使用Get/Set</Type>ArrayRegion系列函数。这些函数会进行越界检查,在需要的时候会有可能抛出ArrayIndexOutOfBoundsException异常。 
对于少量的、固定大小的数组,Get/Set<Type>ArrayRegion是最好的选择,因为C缓冲区可以在Stack(栈)上被很快地分配,而且复制少量数组元素的代价是很小的。这对函数的另外一个优点就是,允许你通过传入一个索引和长度来实现对子字符串的操作。

如果你没有一个预先分配的 C 缓冲区,并且原始数组长度未定,而本地代码又不想在获取数组元素的指针时阻塞的话,使用 Get/ReleasePrimitiveArrayCritical 函数对。就像Get/ReleaseStringCritical函数对一样,这对函数很小心地使用,以避免死锁。

Get/Release<type>ArrayElements 系列函数永远是安全的。JVM 会选择性地返回一个指针,这个指针可能指向原始数据也可能指向原始数据复制。

对象数组:
JNI提供了一个函数对来访问对象数组。GetObjectArrayElement返回数组中指定位置的元素,而SetObjectArrayElement修改数组中指定位置的元素。
与基本类型的数组不同的是,你不能一次得到所有的对象元素或者一次复制多个对象元素。
字符串和数组都是引用类型,你要使用Get/SetObjectArrayElement来访问字符串数组或者数组的数组。

下面的例子调用了一个本地方法来创建一个二维的 int数组,然后打印这个数组的内容:

 class ObjectArrayTest {
private static native int[][] initInt2DArray(int size);
public static void main(String[] args) {
int[][] i2arr = initInt2DArray(3);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(" " + i2arr[i][j]);
}
System.out.println();
}
}
static {
System.loadLibrary("ObjectArrayTest");
}
}

静态本地方法 initInt2DArray 创建了一个给定大小的二维数组。执行分配和初始化数组任务的本地方法可以是下面这样子的:

 JNIEXPORT jobjectArray JNICALL Java_ObjectArrayTest_initInt2DArray(JNIEnv *env, jclass cls, int size)
{
jobjectArray result;
int i;
jclass intArrCls = (*env)->FindClass(env, "[I");
if (intArrCls == NULL) {
return NULL; /* exception thrown */
} result = (*env)->NewObjectArray(env, size, intArrCls, NULL); //分配第一维 if (result == NULL) {
return NULL; /* out of memory error thrown */
} for (i = 0; i < size; i++) {
jint tmp[256]; /* make sure it is large enough! */
int j;
jintArray iarr = (*env)->NewIntArray(env, size); //创建第二维数据
if (iarr == NULL) {
return NULL; /* out of memory error thrown */
}
for (j = 0; j < size; j++) {
tmp[j] = i + j;
}
(*env)->SetIntArrayRegion(env, iarr, 0, size, tmp);
(*env)->SetObjectArrayElement(env, result, i, iarr);
(*env)->DeleteLocalRef(env, iarr);
}
return result;
}

转自:http://www.cnblogs.com/lijunamneg/archive/2012/12/22/2828922.html

 Java_com_array_arrayTest_arrayUse( JNIEnv* env,jobject thiz,jobjectArray arrayData)
{ jint i,j; int row = (*env)->GetArrayLength(env, arrayData);//获得行数 jarray myarray = ((*env)->GetObjectArrayElement(env, arrayData, )); int col =(*env)->GetArrayLength(env, myarray); //获得列数 jint jniData[row][col]; for (i = ; i < row; i++){ myarray = ((*env)->GetObjectArrayElement(env, arrayData, i)); jint *coldata = (*env)->GetIntArrayElements(env, (jintArray)myarray, ); for (j=; j<col; j++) {
jniData [i] [j] = coldata[j]; //取出JAVA类中arrayData的数据,并赋值给JNI中的数组
} (*env)->ReleaseIntArrayElements(env, (jintArray)myarray, coldata, ); } }

JNI——访问数组的更多相关文章

  1. 2 通过JNI混合使用Java和C++ -----> 访问数组

    关于c和cpp实现native方法的一些注释: 1>  在jni.h中首先定义了C的实现方式,然后用内联函数实现了Cpp的实现方式,如下所示: const char* GetStringUTFC ...

  2. android JNI 一维数组、二维数组的访问与使用

    在JNI中访问JAVA类中的整型.浮点型.字符型的数据比较简单,举一个简单的例子,如下: //得到类名 jclass cls = (*env)->GetObjectClass(env, obj) ...

  3. Android 通过 JNI 访问 Java 字段和方法调用

    在前面的两篇文章中,介绍了 Android 通过 JNI 进行基础类型.字符串和数组的相关操作,并描述了 Java 和 Native 在类型和签名之间的转换关系. 有了之前那些基础,就可以实现 Jav ...

  4. smarty访问数组中的数据,如果是关联数组直接用点.

    $tpl=new Smarty();//新建一个smarty对象,我使用的是Smarty-3.1.6版本 1.设置smarty模板路径$tpl->setTemplateDir():默认情况下是t ...

  5. C---通过指针访问数组

    C语言规定:如果指针变量P已指向数组中的一个元素,则P+1指向同一数组中的下一个元素. 引入指针变量后,就可以用俩种方法来访问数组元素了. 如果p的初值为&a[0],则: P+i 和a+i 就 ...

  6. [Android]通过JNI访问并操作Bitmap的元素,支持RGB565和ARGB8888

    [Android]通过JNI访问并操作Bitmap的元素,支持RGB565和ARGB8888 标签: androidbitmapjni 2014-05-09 20:35 2985人阅读 评论(1) 收 ...

  7. perl访问数组中变量

    数组一个是存储标量值的无序列表变量. 数组变量以 @ 开头.访问数组元素使用 $ + 变量名称 + [索引值] 格式来读取,实例如下: #!/usr/bin/perl @names = (" ...

  8. js添加key为数字的对象,通过类似于通过访问数组的中括号形式访问对象属性

    var obj={};obj[1] = "mm";obj[2]="nn";console.log(obj[1]); 同var obj={};obj[" ...

  9. 008android初级篇之jni中数组的传递

    008android初级篇之jni中数组的传递 jni中在native中数据类型的实际类型 jchar 占两个字节,跟native c中的char(占一个字节)是两个数据类型 jbyte, unsig ...

随机推荐

  1. day22面向对象

    面向对象编程: 1.什么是面向对象 面向过程(编程思想): 过程,解决问题的步骤,流程即第一步做什么,第二步做什么 将复杂问题,拆成若干小问题,按照步骤一一解决,将复杂问题流程化(为其制定固定的实现流 ...

  2. MFC中Picture控件显示图像

    图片显示在picture控件中,整个软件最小化后图片消失问题. 解决方案:OpenCV学习笔记(9)利用MFC的Picture控件显示图像+播放视频和捕获摄像头画面 - CSDN博客  http:// ...

  3. Ubuntu14.04使用root登陆帐户

    http://jingyan.baidu.com/article/27fa73268144f346f8271f83.html 1.输入sudo gedit /usr/share/lightdm/lig ...

  4. JMeter学习笔记21-如何添加思考时间

    本文来介绍,JMeter如何插入思考时间.前面介绍过一个真实的性能测试场景,是需要加入思考时间,来模拟真实用户行为.本文就来介绍,如何在三个请求之间添加思考时间. 1. 在Test Plan下新建一个 ...

  5. mysqli 封装

    <?php //header header('content-type:text/html;charset=UTF-8'); class DB { //定义属性 private $host;// ...

  6. BZOJ 2190 [SDOI2008]仪仗队 ——Dirichlet积

    [题目分析] 考虑斜率为0和斜率不存在的两条线上只能看到3人. 其余的人能被看见,当且仅当gcd(x,y)=1 ,然后拿卷积算一算 发现就是欧拉函数的前缀和的二倍. 注意2的情况要特判. [代码] # ...

  7. bzoj1225 [HNOI2001] 求正整数

    1225: [HNOI2001] 求正整数 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 762  Solved: 313[Submit][Statu ...

  8. C++ 中头文件(.h)和源文件(.cc)的写法简述

    用C++编写比较大型的项目时,文件的分割管理确实确实是非常必要的 .下面就非常简洁明了地谈谈头文件(.h)和源文件(.cc)应该怎么写. 头文件(.h):写类的声明(包括类里面的成员和方法的声明).函 ...

  9. vector 类中的 push_back( ) 函数

    函数名 push_back,算法语言里面的一个函数名,如:   1) c++中的vector头文件里面就有这个push_back函数:   2) 在vector类中作用为在vector尾部加入一个数据 ...

  10. ftp链接、上传、下载、断开

    开发环境:Jdk 1.8 引入第三方库:commons-net-2.2.jar(针对第一种方法) 一.基于第三方库FtpClient的FTP服务器数据传输 由于是基于第三方库,所以这里基本上没有太多要 ...