JNI调用——处理Java的数组

可以使用GetFieldID获取一个Java数组变量的ID,然后用GetObjectFiled取得该数组变量到本地方法,返回值为jobject,然后我们可以强制转换为j<Type>Array类型。

可以明白Java的数组,在JNI中都是j<Type>Array的类型。具体的类型如下:如jbooleanArray,jbyteArray等等

[cpp]  view plain copy
  1. typedef jarray jbooleanArray;  
  2. typedef jarray jbyteArray;  
  3. typedef jarray jcharArray;  
  4. typedef jarray jshortArray;  
  5. typedef jarray jintArray;  
  6. typedef jarray jlongArray;  
  7. typedef jarray jfloatArray;  
  8. typedef jarray jdoubleArray;  
  9. typedef jarray jobjectArray;  

j<Type>Array类型是JNI定义的一个对象类型,它并不是C/C++的数组,如int[]数组,double[]数组等等。所以我们要把j<Type>Array类型转换为C/C++中的数组。

JNIEnv定义了一系列的方法来把一个j<Type>Array类型转换为C/C++数组,和把C/C++数组转换为j<Type>Array

[cpp]  view plain copy
  1.  jsize GetArrayLength(jarray array)   
  2.   
  3.  jobjectArray NewObjectArray(jsize len, jclass clazz,jobject init)  
  4.  jobject GetObjectArrayElement(jobjectArray array, jsize index)   
  5.  void SetObjectArrayElement(jobjectArray array, jsize index,jobject val)   
  6.   
  7.  jbooleanArray NewBooleanArray(jsize len)   
  8.  jbyteArray NewByteArray(jsize len)   
  9.  jcharArray NewCharArray(jsize len)   
  10.  jshortArray NewShortArray(jsize len)   
  11.  jintArray NewIntArray(jsize len)   
  12.  jlongArray NewLongArray(jsize len)   
  13.  jfloatArray NewFloatArray(jsize len)   
  14.  jdoubleArray NewDoubleArray(jsize len)   
  15.   
  16.  jboolean * GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy)   
  17.  jbyte * GetByteArrayElements(jbyteArray array, jboolean *isCopy)   
  18.  jchar * GetCharArrayElements(jcharArray array, jboolean *isCopy)   
  19.  jshort * GetShortArrayElements(jshortArray array, jboolean *isCopy)   
  20.  jint * GetIntArrayElements(jintArray array, jboolean *isCopy)   
  21.  jlong * GetLongArrayElements(jlongArray array, jboolean *isCopy)   
  22.  jfloat * GetFloatArrayElements(jfloatArray array, jboolean *isCopy)   
  23.  jdouble * GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy)   
  24.   
  25.  void ReleaseBooleanArrayElements(jbooleanArray array,jboolean *elems,jint mode)   
  26.  void ReleaseByteArrayElements(jbyteArray array,jbyte *elems,jint mode)   
  27.  void ReleaseCharArrayElements(jcharArray array,jchar *elems,jint mode)   
  28.  void ReleaseShortArrayElements(jshortArray array,jshort *elems,jint mode)   
  29.  void ReleaseIntArrayElements(jintArray array,jint *elems,jint mode)   
  30.  void ReleaseLongArrayElements(jlongArray array,jlong *elems,jint mode)   
  31.  void ReleaseFloatArrayElements(jfloatArray array,jfloat *elems,jint mode)   
  32.  void ReleaseDoubleArrayElements(jdoubleArray array,jdouble *elems,jint mode)  
  33.   
  34.  void * GetPrimitiveArrayCritical(jarray array, jboolean *isCopy)   
  35.  void ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode)   
  36.   
  37.  void GetBooleanArrayRegion(jbooleanArray array,jsize start, jsize len, jboolean *buf)   
  38.  void GetByteArrayRegion(jbyteArray array,jsize start, jsize len, jbyte *buf)   
  39.  void GetCharArrayRegion(jcharArray array,jsize start, jsize len, jchar *buf)   
  40.  void GetShortArrayRegion(jshortArray array,jsize start, jsize len, jshort *buf)   
  41.  void GetIntArrayRegion(jintArray array,jsize start, jsize len, jint *buf)   
  42.  void GetLongArrayRegion(jlongArray array,jsize start, jsize len, jlong *buf)   
  43.  void GetFloatArrayRegion(jfloatArray array,jsize start, jsize len, jfloat *buf)   
  44.  void GetDoubleArrayRegion(jdoubleArray array,jsize start, jsize len, jdouble *buf)   
  45.   
  46.  void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len,const jboolean *buf)   
  47.  void SetByteArrayRegion(jbyteArray array, jsize start, jsize len,const jbyte *buf)   
  48.  void SetCharArrayRegion(jcharArray array, jsize start, jsize len,const jchar *buf)   
  49.  void SetShortArrayRegion(jshortArray array, jsize start, jsize len,const jshort *buf)   
  50.  void SetIntArrayRegion(jintArray array, jsize start, jsize len,const jint *buf)   
  51.  void SetLongArrayRegion(jlongArray array, jsize start, jsize len,const jlong *buf)   
  52.  void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len,const jfloat *buf)   
  53.  void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len,const jdouble *buf)   

上面是JNIEnv提供的所有操作数组的方法,大致可以分为下面几类。

1、获取数组的长度

[cpp]  view plain copy
  1. jsize GetArrayLength(jarray array)   
不管是基本类型数组,还是对象类型数组


2、对象类型数组的操作

[cpp]  view plain copy
  1. jobjectArray NewObjectArray(jsize len, jclass clazz,jobject init)  
  2. jobject GetObjectArrayElement(jobjectArray array, jsize index)   
  3. void SetObjectArrayElement(jobjectArray array, jsize index,jobject val)   
JNI没有提供直接把Java的对象类型数组(Object[ ])直接转到C++中的jobject[ ]数组的函数。而是直接通过Get/SetObjectArrayElement这样的函数来对Java的Object[ ]数组进行操作

3、基本数据类型数组的操作

基本数据类型数组的操作方法比较多,大致可以分为如下几类:

①、Get<Type>ArrayElements/Realease<Type>ArrayElements

Get<Type>ArrayElements(<Type>Array arr,jboolean* isCopied);

这类函数可以把Java基本类型的数组转换到C/C++中的数组。有两种处理方式,一是拷贝一份传回本地代码,另一个是把指向Java数组的指针直接传回到本地代码,处理完本地化的数组后,通过Realease<Type>ArrayElements来释放数组

Realease<Type>ArrayElements(<Type>Array arr,<Type>* array,jint mode);用这个函数可以选择将如何处理Java跟C/C++的数组,是提交,还是撤销等,内存释放还是不释放

mode可以取下面的值:

0       对Java的数组进行更新并释放C/C++的数组

JNI_COMMIT    对Java的数组进行更新但是不释放C/C++的数组

JNI_ABORT    对Java的数组不进行更新,释放C/C++的数组


②、GetPrimitiveArrayCritical/ReleasePrimitiveArrayCritical

void * GetPrimitiveArrayCritical(jarray array, jboolean *isCopy) {
void ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode) 

这两个函数也是JDK1.2 新增的,为了增加直接传回指向Java数组的指针而加入的函数,同样的,也会有用GetStringCritical的死锁的问题。


3、Get<Type>ArrayRegion/Set<Type>ArrayRegion

Get<Type>ArrayRegion(<Type>Array arr,jsize start,jsize len,<Type>* buffer)

在C/C++预先开辟一段内存,然后把Java基本类型的数组拷贝到这段内存中,跟GetStringRegion原理相似。

Set<Type>ArrayRegion(<Type>Array arr,jsize start,jsize len,const <Type>* buffer)

把java基本类型 的数组中的指定范围的元素用C/C++的数组中的元素来赋值


看下面的一个对基本数据类型的操作:

Java端代码如下,有一个本地方法和数组

[java]  view plain copy
  1. package com.tao.test;  
  2.   
  3. public class Test {  
  4.     private int [] arrays=new int[]{1,2,3,4,5};  
  5.     public native void show();  
  6.     static{  
  7.         System.loadLibrary("NativeTest");  
  8.     }  
  9.     public static void main(String[] args) {  
  10.         new Test().show();  
  11.     }  
  12. }  
本地方法:

[cpp]  view plain copy
  1. JNIEXPORT void JNICALL Java_com_tao_test_Test_show  
  2.   (JNIEnv * env, jobject obj)  
  3. {  
  4.     jfieldID id_arrsys=env->GetFieldID(env->GetObjectClass(obj),"arrays","[I");  
  5.     jintArray arr=(jintArray)(env->GetObjectField(obj,id_arrsys));  
  6.     jint* int_arr=env->GetIntArrayElements(arr,NULL);  
  7.     jsize len=env->GetArrayLength(arr);  
  8.     for(int i=0;i<len;i++)  
  9.     {  
  10.         cout<<int_arr[i]<<endl;  
  11.     }  
  12.     env->ReleaseIntArrayElements(arr,int_arr,JNI_ABORT);  
  13. }  
最后在Java中调用本地方法,输出了字符串。

你可能感兴趣的:(java,jni)