Overview
This article will explain the data transformations between Java and native code, including conversions between the underlying types, and the transfer and transformation of arrays.
Type conversion table the corresponding table between the Java base type and C + +
Java Type |
C + + type |
Description |
Boolean |
Jboolean |
Unsigned 8-bit integer |
Byte |
Jbyte |
Unsigned 8-bit integer |
Char |
Jchar |
Signed 16-bit integer |
Short |
Jshort |
Signed 16-bit integer |
Int |
Jint |
Signed 32-bit integer |
Long |
Jlong |
Signed 64-bit integer |
Float |
Jfloat |
32-bit single-precision floating-point number |
Double |
Jdouble |
64-bit double-precision floating-point number |
This can be seen from the jni.h header file definition:
typedef unsigned CharJboolean;/ * Unsigned 8 bits * /typedef signed CharJbyte;/ * Signed 8 bits * /typedef unsigned ShortJchar;/ * unsigned-bits * /typedef ShortJshort;/ * Signed-bits * /typedef intJint/ * Signed-bits * /typedef Long LongJlong;/ * Signed bits * /typedef floatJfloat;/ * 32-bit IEEE 754 * /typedef Doublejdouble;/ * 64-bit IEEE 754 * /
As can be seen from the JNI definition code above, the underlying types are converted based on the Java type size equivalence. As a result, the underlying type passed in using Java or returned to the underlying type in Java can be used directly. Like what:
type,jint i) { return i+5;}
The corresponding table between the Java reference type and C + +
Java Type |
C + + type |
Description |
Objec |
Jobject |
Any Java object |
Class |
Jclass |
Class object |
String |
Jstring |
String Class object |
Object[] |
Jobjectarray |
Object array |
Boolean[] |
Jbooleanarray |
Boolean array |
Byte[] |
Jbytearray |
byte array |
Char[] |
Jchararray |
Array of character types |
Short[] |
Jshortarray |
Short integer Array |
Int[] |
Jintarray |
Array of integral type |
Long[] |
Jlongarray |
Long Integer Array |
Float[] |
Jfloatarray |
Floating-point arrays |
Double[] |
Jdoublearray |
Double-precision floating-point array |
/ * * Reference types, in C + + *class_jobject {};class_jclass: Public_jobject {};class_jstring: Public_jobject {};class_jarray: Public_jobject {};class_jobjectarray: Public_jarray {};class_jbooleanarray: Public_jarray {};class_jbytearray: Public_jarray {};class_jchararray: Public_jarray {};class_jshortarray: Public_jarray {};class_jintarray: Public_jarray {};class_jlongarray: Public_jarray {};class_jfloatarray: Public_jarray {};class_jdoublearray: Public_jarray {};class_jthrowable: Public_jobject {};typedef_jobject* Jobject;typedef_jclass* Jclass;typedef_jstring* jstring;typedef_jarray* Jarray;typedef_jobjectarray* Jobjectarray;typedef_jbooleanarray* Jbooleanarray;typedef_jbytearray* Jbytearray;typedef_jchararray* Jchararray;typedef_jshortarray* Jshortarray;typedef_jintarray* Jintarray;typedef_jlongarray* Jlongarray;typedef_jfloatarray* Jfloatarray;typedef_jdoublearray* Jdoublearray;typedef_jthrowable* jthrowable;typedef_jobject* Jweak;
From the definition in JNI, you can see that any reference type (the array is also referenced in Java) is passed into C + + just a pointer to a Java object. So the reference type cannot be used directly, JNIENV provides a number of ways to accomplish the conversion between them.
Using jnienv to complete conversions between data
This only describes conversions between referenced objects, because Java is interoperable with C + + for normal types.
The passing of a string
The string is explained here separately because string has a very high frequency of use in Java, and JNIEnv has a corresponding conversion function to string. The functions in JNI are defined as follows:
/** converted to Unicode-related functions */ jstring NewString (const jchar*, jsize); Jsize getstringlength (jstring); const jchar* getstringchars (jstring, jboolean* iscopy); void Releasestringchars (jstring, const jchar*); /** convert to UTF-8 related functions */ jstring Newstringutf (const char *); jsize getstringutflength (jstring); const char * getstringutfchars (jstring, jboolean* iscopy); void Releasestringutfchars (jstring, const char *);
When the string B is returned from the JNI function getstringchars, if B is a copy of the original string java.lang.String, the iscopy is assigned the value jni_true. If B and the original string point to the same piece of data in the JVM, Iscopy is assigned a value of Jni_false.
When the Iscopy value is Jni_false, the local code must not modify the contents of the string, otherwise the original string in the JVM will be modified, which breaks the immutable rules of the string in the Java language.
Usually, because you don't have to worry about whether the JVM will return a copy of the original string, you only need to pass NULL as the parameter for iscopy.
From the above code, we can clearly see that the string processing function is divided into Unicode and UTF-8 two encoding types, but in Android using the UTF-8-related functions, the two encodings provide the same functionality, from the function name can see the function of the corresponding function. Here's an example of using a C + + merge string to demonstrate how to use:
//Java中定义Native函数publicnativestaticstrConcat(String str1,String str2);
//Generate C + + functions and implement string join function with C + +#include "string.h"Jniexport jstring jnicall java_com_example_wastrel_test_test_strconcat (jnienv *env, Jclass clazz, jstring str1, JS Tring str2) {//Convert jstring to const char* pointer, use the const modifier to indicate that its contents cannot be modified Const Char* C1=env->getstringutfchars (STR1, NULL);Const Char* C2=env->getstringutfchars (STR2, NULL);//Calculate the length of the new string intSize=strlen(C1) +strlen(C2);//Create a new string, where length +1 is for the string to have a trailing mark ' \ S ' Char* n_char=New Char[size+1];//Use the string manipulation method provided by the C standard library to concatenate strings, where the include "String.h" header file is required strcpy(N_CHAR,C1);strcat(N_CHAR,C2);//Converts the generated new string to UTF jstringJstring Rs=env->newstringutf (N_char);//Delete the memory just allocated to avoid causing a memory leak Delete[] N_char;//Notifies the JVM that the virtual machine native code is not holding a reference to the string, stating that the white point is telling the virtual machine I am not using it, you can recycle it. //Because if the object is referenced in the JVM, the object will not be recycled. //Why do you pass jstring and generated char* here? It is because char* may be a copy of jstring, and if it is a copy, then char* should be deleted. Env->releasestringutfchars (STR1,C1); Env->releasestringutfchars (STR2,C2);returnRS;}
//然后我们在Java中调用该函数print(Test.strConcat("里约奥运",",中国加油"));
Note: The print function used in this section and later in the code is simply to append the results to the TextView on the interface, as shown in the code below:
privatevoidprint(String str){ tv.append(str+"\n");}
To generate the C Function procedure, please refer to the previous article: http://blog.csdn.net/venusic/article/details/52121254/
Operation Result:
Array delivery of the underlying data
Array passing, like string passing, native receives a reference form, so jnienv also provides some column methods to complete the conversion of the data. Because the method of invocation between different data types is basically the same, the int array is used here as the explanation, and int[] is passed to native after the Jintarray object is received.
//Get the length of the array, this method applies to all Jarray objectsJsize Getarraylength (JarrayArray)//Create a Jint array locally, this array can only be assigned by Setintarrayregion. Jintarray Newintarray (jsize length);//Convert Jintarray to Jint pointerjint* getintarrayelements (JintarrayArray, jboolean* iscopy);//Take out some elements of the array and put them in the BUF.voidGetintarrayregion (JintarrayArray, jsize start, Jsize len, jint* buf);//Assign values to Jintarray by intervalvoidSetintarrayregion (JintarrayArray, jsize start, Jsize Len,Constjint* buf);//Release Jntarray, the first parameter represents the passed Jintarray, the second parameter represents the local array pointer obtained to the///The third parameter needs to be highlighted, which has three values: 0, Jni_commit, Jni_abort//value 0 (0), update the array and release all elements;//value jni_commit, update but do not release all elements;//value Jni_abort, do not update but release all elements;//0 more in general practical applicationsvoidReleaseintarrayelements (JintarrayArray, jint* elems,jint mode);
Example 1: array of int from JNI
//Java中定义Native函数,size表示返回数组的大小publicnativestaticintgetIntArray(int size);
//Generate native function and implement method#include"Stdlib.h"#include"Time.h"//define random number to generate a macro to represent a random number between 0~x#define RANDOM (X) (Rand()%x) Jniexport Jintarray jnicall Java_com_example_wastrel_test_test_getintarray (jnienv*env, Jclass Clazz, Jintsize){//initialization of random number generator with time variableSrand ((int) Time (0)); jint* rs=new jint[size]; for(intI=0;i<size; i++) {//Call macro to generate 0~100 random numberRs[i]=random ( -); }//Through JNIEnv Newintarray method new A Jintarray objectJintarray array=Env->newintarray (size);//Assign the resulting random value to Jintarray Env->setintarrayregion (Array,0,size, RS);returnArray;}
//java call function int []rs=test.getintarray (10 );p rint ( "from the JNI int array" ); Print (Intarraytostring (RS)); /** convert int[] to comma-separated helper functions for easy display */ private String intarraytostring (int [] ints) { StringBuilder str=new StringBuilder (); Str.append ( "[' ]; for (int i:ints) {str.append (i); Str.append ("); } Str.deletecharat (Str.length ()-1 ); Str.append (); return str.tostring ();}
Operation Result:
Example 2: Use JNI to sort the array returned by example 1
//声明Java Native函数,参数为int[]publicnativestaticvoidsortIntArray(int []ints);
//implement C + + functionsJniexport void Jnicall Java_com_example_wastrel_test_test_sortintarray (jnienv*env, Jclass clazz, Jintarray array) {//Get the array length passed overJsizesize=Env->getarraylength (array);//convert array to Java pointerjint* jints=Env->getintarrayelements (Array,null);//Simple bubble sort for(inti =0; I <size-1; ++i) { for(intj =0; J <size-1-I.; ++J) {if(jints[j]<jints[j+1]) {intT=JINTS[J]; jints[j]=jints[j+1]; jints[j+1]=t; } } }//Update the sorting results to the Java array, the third parameter equals 0 to update to the original array and release all elements Env->releaseintarrayelements (Array,jints,0);return;}
//在Java中调用print("通过JNI对int数组排序:");Test.sortIntArray(rs);print(IntArrayToString(rs));
As you can see here, instead of returning an array, we update the results to the Java array through the Releaseintarrayelements function. Our array values in Java have changed.
Operation Result:
Passing of other base type arrays
Array passing in other underlying types is almost identical to int[], and the function names are replaced by their respective types. Here is not too much to narrate, I would like to have the above example, it is easy to understand the other basic data types to pass the use.
Example program: http://download.csdn.net/detail/venusic/9604128
Android Studio NDK Getting Started Tutorial (2) Simple data conversion and delivery between--java and C + +