android jni——basic Types, Strings and Arrays

 學習一門新的編程語言,數據類型是最基本的東西,這裡我們講述下jni中的數據類型。

在JNI中把數據類型分為3類:

primitive type:int float char

reference type:class instances arrays

string type

在 HelloWorld中我們打印出HelloWorld等字樣,我們沒有傳入任何參數,這裡先給出一個例子,我們在java端傳入字符串,然後看在jni中時如何做處理的。

這個例子跟之前的Helloworld差不多,稍作修改,我們在java端傳入參數,

新建一個類,專門用來封轉jni的method:

[java]
 package com.android.jni; 
 
public class Prompt { 
    public native String getLine(String prompt); 
    static { 
        System.loadLibrary("MyJNI"); 
    } 
 

在主activity中調用:

[java]
//調用原生函數得到字符串str 
Prompt pmt = new Prompt(); 
String str=pmt.getLine("Put in a line!"); 
//吐出message 
Toast.makeText(mContext, str, Toast.LENGTH_SHORT).show(); 
         

我們調用瞭Prompt中的getLine方法。

然後看下C中的代碼:

[cpp]
jstring 
Java_com_android_jni_Prompt_getLine(JNIEnv* env,jobject jobj,jstring prompt) 

    char buf[128]; 
    const jbyte *str; 
    str = (*env)->GetStringUTFChars(env,prompt,NULL); 
    if(str == NULL) 
        return NULL; 
    __android_log_print(ANDROID_LOG_INFO,"-JNI-","%s",str); 
    (*env)->ReleaseStringUTFChars(env,prompt,str); 
    sprintf(buf,"From C + %s",str); 
    return (*env)->NewStringUTF(env,buf); 

getLine函數呼叫瞭JNI的功能函數GetStringUFTChars來讀取我們傳入的prompt字符串(java端)。GetStringUFTChars函數進入JNIEnv 結構指針,把java中的UTF-8字符類型轉變成C中的Unicode sequence,轉換成jstring 參考來使用。

最後在釋放str的時候不要忘記檢查str是否為空,因為GetStringUFTChars函數可能會調用失敗(outofmenory)。

當原生代碼把傳進來的UTF-8類型字符串之後應該立即釋放內存調用ReleaseStringUTFChars。

調用NewStringUTF函數來構建新的字符串return給java代碼。

在模擬器中運行,當我們點擊按鈕的時候會出現字符串,“From C + 。。。”

 

 

調用成功。

———————————————————————————

下面我們來進入數組,先看下面的數組定義:

int[] iarr;

float[] farr;

Object oarr;

int[][] arr2;

iarr和farr是數據數組,但是oarr和arr2是對象數組。

下面舉個例子進入數據數組:

先看下我們要實現的,在java代碼中:

 

 

[cpp]
 //調用原生函數得到字符串str 
//Prompt pmt = new Prompt(); 
//String str=pmt.getLine("Put in a line!"); 
int arr[] = new int[10]; 
for(int i=0;i<10;i++) 
    arr[i]=i; 
int sum = IntArray.sumArray(arr); 
//吐出message 
Toast.makeText(mContext, "sum = "+sum, Toast.LENGTH_SHORT).show(); 

 

封裝動態庫function:

[cpp]
 package com.android.jni; 
 
public class IntArray { 
    public native static int sumArray(int[] arr); 
 
    static { 
        System.loadLibrary("IntArray"); 
    } 

 

定義一個數組,然後調用jni中的function來對數組進行操作,這邊在java代碼中傳進去的是一個整形的數組。

———————————————————————————————–

我們來看下在jni中是如何處理的:

[cpp]
jint 
Java_com_android_jni_Native_sumArray(JNIEnv* env,jobject jobj,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; 

 

這裡調用瞭GetIntArrayRegion函數來把傳進來的arr數組中的數據都拷貝進C,該函數第三個參數是索引的開始值,第四個參數是被拷貝的數。

JNI也可以使用Get/Release<Type>ArrayElements 函數來使原生代碼直接擁有數組的指針。

[cpp]

Java_com_android_jni_Native_sumArray(JNIEnv* env,jobject jobj,jintArray arr) 

//  jint buf[10]; 
    jint *carr; 
    jint i, sum = 0; 
//  (*env)->GetIntArrayRegion(env,arr,0,10,buf); 
    carr = (*env)->GetIntArrayElements(env,arr,NULL); 
    if(carr == NULL) 
        return 0; 
    for(i=0;i<10;i++) 
        sum += carr[i]; 
    (*env)->ReleaseIntArrayElements(env,arr,carr,0); 
    return sum; 

運行模擬器:

 
 

—————————————————————————————-

下面我們來看下jni中對對象數組的處理。

看下原生函數的聲明

[cpp]
 public static native int[][] intitInt2DArray(int size);  

下面是jni中的實現

[cpp] v
 jobjectArray 
Java_com_android_jni_Native_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; 

——————————————————————————————

ok,我們的基本數據類型就介紹到這,這裡數據類型還有很多,大傢可以參考user guide,一般我遇到新類型就去翻資料。

下面我們會介紹jni是如何調用java中的成員函數和成員變量的。

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *