Ndk/jni Develop Guide (4) How to use Array

Source: Internet
Author: User

Ndk/jni Develop Guide (4) How to use Array

The array in JNI is divided into primitive type arrays and object arrays, which are handled differently, and all elements in the primitive type array are JNI
The basic data type that can be accessed directly. Whereas all elements in an object array are references to instances or other arrays of a class, and string manipulation
, you cannot directly access the array that Java passes to the JNI layer, and you must select the appropriate JNI function to access and set the Java layer's array object. Read
Read this article to assume that you have already understood the mappings between JNI and the Java data type. The following is an example of an int type that describes the accessors of an array of basic data types
, the object array type uses an example of creating a two-dimensional array to demonstrate how to access:

 Public  class mainactivity extends appcompatactivity {    Static{System.loadlibrary ("Math");//Load library to Android project}Private int[] Array = {0,1,2,3,4,5,6,7,8,9};PrivateTextView Sumtxt;PrivateTextView Printarr;@SuppressLint("Defaultlocale")@Override    protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate);        Setcontentview (R.layout.activity_main);        Sumtxt = (TextView) Findviewbyid (r.id.sun_txt);        Printarr = (TextView) Findviewbyid (R.id.print_arr); Intarray Intarray =NewIntarray ();intsum = Intarray.sumarray (array); Toast.maketext ( This,"The attays sum is"+ Sum, toast.length_short). Show (); Sumtxt.settext ("The attays sum is"+ sum);int[] arr = Intarray.initint2darray (3); StringBuilder StringBuilder =NewStringBuilder (); for(inti =0; I <3; i++) {//get the arrays and add those into builder             for(intj =0; J <3; J + +) {Stringbuilder.append (String.Format ("arr[%d][%d] =%d\n", I,j,arr[i][j])); System.out.format ("arr[%d][%d] =%d\n", I, J, Arr[i][j]); }} printarr.settext (Stringbuilder.tostring ());//show on the TextView}}

The following two local methods are written:

/** * Created by BlueZhang on 16/6/28. * * @Author : Bluezhang * @date : 16/6/28 */< /span>public  class  intarray  { public  native  int  sumarray  (int  [] arr);    //caculate the sum of array from Java  public  native  int  [] initint2darray  (int  size); //init the array and return the result }  

Here's a look at the implementation of our native code:

////Created by Bluezhang on 16/6/28.//#include"Sum.h"#include"Stdlib.h"#include"String.h"/* * Class:com_example_bluezhang_ndkarraytest_intarray * Method:sumarray * Signature: ([i) I/ *Jniexport jint jnicall Java_com_example_bluezhang_ndkarraytest_intarray_sumarray (jnienv *env, Jobject obj, JINTARR Ay j_array) {jint I, sum =0;    Jint *c_array; Jint Arr_len;//1. Get the length of the arrayArr_len = (*env)->getarraylength (env, J_array);//2.get The buffer (Java array Element) from memory depend on data typeC_array = (Jint *) malloc (sizeof (jint) * Arr_len);//3. Clear the cache areamemset (C_array Initialize buffer,0, sizeof (jint) * Arr_len);//4. Copy all elements in the Java array to the buffer(*env)->getintarrayregion (env, J_array,0, Arr_len, C_array); for(i =0; i < Arr_len; i++) {sum + = C_array[i];//5. Sum all elements} free (C_array);//6. Release the buffer    returnSum//Jint i, sum = 0;//Jint *c_array;//Jint Arr_len;//// discontinuous in memory of the elements in an array, the JVM could copy all the raw data to the buffer , and then return a pointer to the buffer//C_array = (*env)->getintarrayelements (env,j_array,null);//if (C_array = = NULL) {//return 0; Copy into the buffer faliure//      }//Arr_len = (*env)->getarraylength (Env,j_array);//printf ("Arr_len =%d\n", Arr_len);//for (i = 0; i < Arr_len; i++) {//Sum + = C_array[i];//      }//(*ENV)->releaseintarrayelements (Env,j_array, C_array, 0);//release the buffer//return sum;}/* * Class:com_example_bluezhang_ndkarraytest_intarray * Method:initint2darray * Signature: (i) [[I */Jniexport jobjectarray jnicall Java_com_example_bluezhang_ndkarraytest_intarray_initint2darray (JNIEnv *env, Jobjec    T obj, jint size) {Jobjectarray result;    Jclass Clsintarray; Jint i,j;//1.Get an int type 2 D array class referenceClsintarray = (*env)->findclass (env,"[I");if(Clsintarray = = NULL) {returnNULL; }//2.Create An array object (the inside Clsintarray in each element)result = (*env)->newobjectarray (env,size,clsintarray,null);if(Result = = NULL) {returnNULL; }//3.assignment for array element     for(i =0; i < size; ++i) {Jint buff[ the]; Jintarray intarr = (*env)->newintarray (env,size);if(Intarr = = NULL) {returnNULL; } for(j =0; J < size;        J + +) {Buff[j] = i + j; } (*env)->setintarrayregion (Env,intarr,0, Size,buff);        (*env)->setobjectarrayelement (Env,result, I, intarr);    (*env)->deletelocalref (Env,intarr); }returnResult;}

Here we explain again how to generate the. h file using Android Studio:

首先进入到我们的目录:/Users/bluezhang/Desktop/NDKArrayTest/app/build/intermediates/classes/debug使用命令:javah -jni packagename.classname这样生成我们的.h文件其实可以添加参数指定生成的目录以及名称这里掠过。

In the above example, a Sumarray native method is defined in Java, the parameter type is int[], corresponding to the Jintarray type in the JNI.
In the local code, the length of the array is obtained first through the Getarraylength function of JNI, the known quantity group is the Jintarray type and can be
The element type of the array is Jint, and then the buffer of the corresponding size is requested, based on the length of the arrays and the type of elements. If the buffer is small
, you can also request memory directly on the stack, which is more efficient, but less flexible, because the size of the Java array has changed, and the local generation
Code is also modified accordingly. The Getintarrayregion function is then called to copy all elements in the Java array into the C buffer and accumulate the array
And finally releases the C buffer that stores the Java array element and returns the computed result. getintarrayregion function 1th
parameter is the JNIENV function pointer, the 2nd parameter is the Java array object, the 3rd parameter is the starting index of the copy array, and the 4th parameter is the
The length of the shell array, and the 5th parameter is the copy destination. Here we have the first step of the work mood is complete, now we have to do is to configure their own project Build.gradle file. Generate the. So file so that we can invoke the. So file after the creation of our purpose is to count
The array is counted and initialized with an array and fed back to the Java code so that it can be displayed using the resulting array.
In the code above, we use one way to calculate the data, the code for the following comment is another way of implementing it. Interested can be manually implemented by themselves
, consult the relevant information.

Summary
1、对于小量的、固定大小的数组,应该选择Get/SetArrayRegion函数来操作数组元素是效率最高的。因为这对函数要求提前分配一个C临时缓冲区来存储数组元素,你可以直接在Stack(栈)上或用malloc在堆上来动态申请,当然在栈上申请是最快的。有童鞋可能会认为,访问数组元素还需要将原始数据全部拷贝一份到临时缓冲区才能访问而觉得效率低?我想告诉你的是,像这种复制少量数组元素的代价是很小的,几乎可以忽略。这对函数的另外一个优点就是,允许你传入一个开始索引和长度来实现对子数组元素的访问和操作(SetArrayRegion函数可以修改数组),不过传入的索引和长度不要越界,函数会进行检查,如果越界了会抛出ArrayIndexOutOfBoundsException异常。2、如果不想预先分配C缓冲区,并且原始数组长度也不确定,而本地代码又不想在获取数组元素指针时被阻塞的话,使用Get/ReleasePrimitiveArrayCritical函数对,就像Get/ReleaseStringCritical函数对一样,使用这对函数要非常小心,以免死锁。3、Get/Release<type>ArrayElements系列函数永远是安全的,JVM会选择性的返回一个指针,这个指针可能指向原始数据,也可能指向原始数据的复制。
Accessing an array of objects

We can see an excuse for two jni in the code that was just generated:

/* * class:com_example_ Bluezhang_ndkarraytest_intarray * Method:sumarray * Signature: ([i) I */ jniexport jint jnicall java_com_example_ Bluezhang_ndkarraytest_intarray_sumarray (JNIEnv *, Jobject, Jintarray); /* * class:com_example_bluezhang_ndkarraytest_intarray * Method:initint2darray * Signa Ture: (i) [[i */ jniexport Jobjectarray jnicall Java_com_example_bluezhang_ndkarraytest_intarray_ Initint2darray (JNIEnv *, Jobject, jint);  

The second method generated is that we want to access an array of objects in Java initialized to an array of two-dimensional arrays of 3*3, the value of the array element is the element angle label
and returns the array.
The local function Initint2darray first invokes the JNI function Findclass obtains a reference to a two-dimensional array class of type int, passed to
The Findclass parameter "[I] is the JNI class descript (JNI type descriptor, which is described in detail later) and corresponds to the JVM
Type of int[]. If the int[] class fails to load, Findclass returns null and throws a
Java.lang.NoClassDefFoundError: [i exception.] Next, Newobjectarray creates a new array, the number
The element types inside the group are represented by the INTARRCLS (int[]) type. The function Newobjectarray can only be assigned the first dimension, and the JVM does not
Data structures corresponding to multidimensional arrays, and JNI does not provide similar functions for creating two-dimensional arrays. Because the two-dimensional array in the JNI is directly manipulated
Is the data structure in the JVM, it is much more complex to create a two-dimensional array than Java and C + +. The way to set up data for a two-dimensional array is also very straightforward,
First create a JNI int array with Newintarray, allocate space for each array element, and then use the Setintarrayregion
Copy the contents of the buff[] buffer into the newly allocated one-dimensional array, and finally assign the int[] array to jobjectarray in the outer loop.
Array, a one-dimensional array in a single-dimensional array, forming a so-called two-dimensional array. In addition, in order to avoid intra-cycle
A large number of JNI local references, causing the JNI reference table to overflow, so in the outer loop every time to call Deletelocalref will create a new
The Jintarray reference is removed from the reference table. In Jni, only Jobject and subclasses are reference variables, which consumes the space of the reference table.
, Jint,jfloat,jboolean, and so on are basic type variables that do not occupy the reference table space, i.e. they do not need to be freed. Reference Table Maximum Space
is 512, and if this range is exceeded, the JVM will be hung off.

Ndk/jni Develop Guide (4) How to use Array

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.