android jni——basic Types, Strings and Arrays

來源:互聯網
上載者:User

 學習一門新的程式設計語言,資料類型是最基本的東西,這裡我們講述下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,我們的基礎資料型別 (Elementary Data Type)就介紹到這,這裡資料類型還有很多,大家可以參考user guide,一般我遇到新類型就去翻資料。

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

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.