JNI程式設計之java層和native層的陣列資料的互動

2023-10-18 18:00:27

一.前言

  JNI中的陣列型別分為基本型別陣列和參照型別陣列,他們的處理方式是不一樣的。基本型別陣列中的元素都是jni基本資料型別,可以直接存取;但是參照型別的陣列中的元素是一個類的範例,不能直接存取,需要使用jni中的函數進行存取。

二.基本型別陣列的互動

  1.java層宣告的native函數如下:

public native double[] arrayAsArgs(int[] a);//求陣列的和以及平均數,並以陣列的形式返回

  2.native層程式碼:

jdoubleArray native_arrayAsArgs(JNIEnv *env,jobject thiz,jintArray array){
    jint *a=env->GetIntArrayElements(array, nullptr);//獲取java層陣列的值,並賦給jint*指標變數
    jsize length=env->GetArrayLength(array);//獲取java層陣列的長度
    jint sum=0;
    jdouble avg=0.0;
    for(int i=0;i<length;i++){
        sum+=*(a+i);//存取每一個陣列元素並累加
    }
    avg=(jdouble)sum/length;
    env->ReleaseIntArrayElements(array,a,0);//和GetIntArrayElements()是一對的,使用完之後就要釋放記憶體,防止記憶體漏失
    jdouble result[]={(jdouble)sum,avg};
    jdoubleArray result1=env->NewDoubleArray(2);//開闢記憶體空間,相當於new double[2]
    env->SetDoubleArrayRegion(result1,0,2,result);//給陣列賦值
    return result1;
}

 三.參照型別陣列的互動

  1.java層宣告的native函數如下:

public native String[] quoteArrayAsArgs(String[] s);//從java中傳入參照陣列到native層,並返回相同的參照陣列到java層

  2.native層程式碼:

jobjectArray native_quoteArrayAsArgs(JNIEnv *env,jobject thiz,jobjectArray s){
    jclass clazz=env->FindClass("java/lang/String");
    jsize length=env->GetArrayLength(s);
    jstring str;
    jstring str1[length];
    for(int i=0;i<length;i++){//獲取java層參照陣列中每個元素的值,並儲存在str1陣列中
        str=(jstring)env->GetObjectArrayElement(s,i);
        str1[i]=str;
    }
    jobjectArray str2;
    str2=env->NewObjectArray(length,clazz, nullptr);//為參照陣列開闢記憶體,相當於new String[length]
    for(int i=0;i<length;i++){
        env->SetObjectArrayElement(str2,i,str1[i]);
    }
    return str2;
}

四.二維陣列的互動

  二維陣列可以看作特殊的一維陣列,陣列中的每個元素的型別是一維陣列,也就是說每個元素是一個參照型別的資料,這樣理解之後,程式碼就好寫了。

  1.java層宣告的native函數如下:

public native char[][] twoDimenArrayAsArgs(char[][] c);//原封不動的返回c

  2.native層程式碼:

jobjectArray native_towDimenArrayAsArgs(JNIEnv *env,jobject thiz,jobjectArray c){
    jsize rows=env->GetArrayLength(c);//獲取行數
    jcharArray cc=(jcharArray)env->GetObjectArrayElement(c,0);
    jsize cols=env->GetArrayLength(cc);//獲取列數
    jchar result[rows][cols];
    for(int i=0;i<rows;i++){
        cc=(jcharArray)env->GetObjectArrayElement(c,i);
        jchar *character=env->GetCharArrayElements(cc, nullptr);
        for(int j=0;j<cols;j++){
            result[i][j]=*(character+j);
        }
        env->ReleaseCharArrayElements(cc,character,0);
    }
    jclass clazz=env->FindClass("[C");//char[]的Class物件
    jobjectArray ret=env->NewObjectArray(rows,clazz, nullptr);
    for(int i=0;i<rows;i++){
        jcharArray jcharArray=env->NewCharArray(cols);
        env->SetCharArrayRegion(jcharArray,0,cols,result[i]);
        env->SetObjectArrayElement(ret,i,jcharArray);
    }
    return ret;
}

  如果是其他型別的陣列,將型別換成其他型別即可,程式碼不用變。