【Android應用開發】-(15)JNI—-基礎資料型別 (Elementary Data Type)

來源:互聯網
上載者:User

前一篇拙文分析JNI的經典執行個體。這篇拙文將通過執行個體的方式來簡易學習JNI的資料類型。任何語言都有其基本的資料類型,要深入瞭解,必須要瞭解最基礎的東西,在JNI中,我們會問:Java語言中的資料類型是如何映射到C/C++本地語言中的呢?

目錄:

   1. 一個簡單的執行個體分析

    2. Java與JNI資料類型的映射

    3. 字串的處理

    4. 數組的處理


1. 一個簡單的執行個體分析編程中,向函數傳參和函數傳回值是很普遍的事情,這裡就通過幾個執行個體介紹這些技術。先通過一個簡單的執行個體來入門吧。這裡擴充HelloWorld.java,先列印一段字串,然後等待使用者輸入,看代碼:(這裡我只列出C的代碼)

  JNIEXPORT jstring JNICALL Java_org_winplus_basetype_HelloWorld_getLine (JNIEnv *, jobject, jstring);//(這串代碼怎麼來的,請看【Android應用開發】-(14)JNI----經典執行個體分析 )

我們看getLine這個函數接收三個參數JNIEnv,jobject,jstring。其中JNIEnv包括JNI的函數表,如:

jobject的意義取決於該方法是靜態還是執行個體方法,當本地方法作為一個方法時,jobject相當於對象本身,即this。當本地方法作為一個靜態方法時,指向所在類。在本執行個體中,getline是一個本地執行個體方法實現,所以jobject指向對象本身。

2. 類型的映射

按資料類型來說,java中有兩種資料類型,基本的資料類型(int float,char),另一種是參考型別(執行個體、數組)。在本地方法(native 聲明的方法)中聲明的參數類型,在JNI中都有對應的類型。

Java與JNI基本類型的映射很直接,請看下錶:

Java                                                 

Native(jni.h)                                    

boolean

jboolean

byte

jbyte

char

jchar

short

jshort

Int

jint

long

jlong

Float

jfloat

double

jdouble

除了這些類型之外還定義了jstring,jclass,jobjectArray等結構。他們都繼承自jobject.

相比基本類型,物件類型的傳遞要複雜很多。Java層的對象對象以(opaque references)指標的形勢傳遞到JNI層。opaque references是C的指標類型,它指向JavaVM內部資料結構。使用這種指標的目的是:不希望JNI使用者瞭解JAVAVM內部資料結構。對opaque references所指結構的操作,都要通過JNI方法進行。比如,”java.lang.String”對象,JNI層對於的類型為jstring,對該opaque references的操作要通過JNIEnv->GetStringUTFChars進行。這裡需要注意的是:編程的過程中一定要按照原則編程,千萬不要為了效率或者容易渠道某個值而繞過JNI,直接操作opaque references。

3. 字串處理

1) 執行個體

現在我們回到執行個體中,看如何處理從java傳過去的String類型,請看下面代碼?

JNIEXPORT jstring JNICALL Java_org_winplus_basetype_HelloWorld_getLine (JNIEnv *env, jobject obj, jstring prompt){Printf(“%s”,prompt);}

很抱歉,出錯了:incorrect use of jstring as a char* pointer。

這裡需要使用對於JNI函數把jstring裝好為C/C++字串。JNI支援Unicode/UTF-8字元編碼互轉。Unicode 以16-bits值編碼;UTF-8是一種以位元組為單位變長格式的字元編碼,並與7-bits ASCII碼相容。UTF-8字串與C字串一樣,以NULL('\0')做結束符, 當UTF-8包含非ASCII 碼字元時,以'\0'做結束符的規則不變。7-bit ASCII字元的取值範圍在 1-127之間,這些 字元的範圍與UTF-8中相同。當最高位被設定時,表示多位元組編碼。如下,調用GetStringUTFChars,把一個Unicode字串轉成UTF-8格式字串,如果你確定字串只包含7-bit ASCII字元。這個字串可以使用C庫中的相關函數,如printf.

Java_org_winplus_basetype_HelloWorld_getLine (JNIEnv *env, jobject obj, jstring prompt){char buf[128];     const jbyte *str;     str =  (*env)->GetStringUTFChars(env, prompt, NULL);     if  (str == NULL) {       return NULL; /* OutOfMemoryError already thrown */     }     printf("%s , str);      (*env)->ReleaseStringUTFChars(env, prompt, str);     /* We assume here that the user does not type more than 127 characters */     scanf("%127s , buf);   return  (*env)->NewStringUTF(env, buf); }

這裡一定要檢測GetStringUTFChars的傳回值,因為調用該函數會有記憶體配置操作。失敗有該函數返回NULL,並拋出OutOfMemoryError異常。發生異常不會改變代碼的執行軌跡,所以當返回Null時要及時處理異常。

1) 釋放GetStringUTFChars調用時的記憶體使用量。ReleaseStringUTFChars

2) 構造新的字串使用JNIEnv->NewStringUTF,同樣的,如果沒有足夠的記憶體也會拋出OutOfMemoryError異常。

3) 其他字串操作方法

GetStringChars是有Java 內部Unicode到本地UTF-8的轉換函式,可以調用 GetStringLength,獲得以Unicode編碼的字串長度。也可以使用strlen計算 GetStringUTFChars的傳回值,得到字串長度。 

const jchar * GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy);

具體的使用請參考JNI詳解16-20頁

4. 數組的操作

Java部分代碼很簡單,不貼出來了。我們直接看C代碼。

JNIEXPORT jint JNICALL Java_org_winplus_basetype_IntArray_sumArray(JNIEnv *env,jobject obj, jintArray arr) {// 我們不能直接這樣操作。/* This program is illegal! *//*int i, sum = 0; for (i = 0; i < 10; i++) { sum += arr[i]; }*///////////////////////////////////範例程式碼1/////////////////////////////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;///////////////////////////////////範例程式碼2///////////////////////////jint *carr;jint j, sum1 = 0;carr = (*env)->GetIntArrayElements(env, arr, NULL);if (carr == NULL) {return 0; /* exception occurred */}for (j = 0; j < 10; j++) {sum1 += carr[j];}(*env)->ReleaseIntArrayElements(env, arr, carr, 0);return sum1;

在範例程式碼1中,使用GetIntArrayRegion拷貝數組內容到buf中,這裡沒有做越界異常檢測,因為知道數組有10個,參數3為待拷貝數組的起始位置,參數4為拷貝元素的個數。

JNI支援SetIntArrayRegion允許重新設定數組一個地區的值,其他基本類型(boolean,short, 和float)也有對應的支援。

範例程式碼2示範通過Get/Release<Type>ArrayElemetns返回Java數組的一個拷貝(實現優良的VM,會返回指向Java數組的一個直接的指標,並標記該記憶體地區,不允許被GC)。


PS:JNI的內容還是有很多。這兩篇JNI主要來自JNI詳解,接下來的內容還是看看文檔吧。這兩篇文章的目的是做一個簡單的入門介紹。實踐出真知!!

文檔:http://download.csdn.net/detail/tangcheng_ok/4435832

原創文章,轉載請註明出處: http://blog.csdn.net/tangcheng_ok

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.