Android JNI學習筆記(四)-資料類型映射以及native調用java

來源:互聯網
上載者:User

標籤:修改   分享   native   lan   語言   field   情況   gen   from   

1. 前言

前幾篇學習了jni開發的基本流程、動態註冊native函數以及相關編譯檔案的編寫,咱們也算是知道了jni開發,但是還不夠,今天咱們來學習下,java和jni的資料類型映射(說白了就是對應關係),以及如何在jni層調用java層的一些東西。偷偷告訴你們,這些全在jni.h檔案裡。

2. 資料類型映射

首先是我們的基礎資料型別 (Elementary Data Type),其關係如下表描述這樣。

上面關係的相關代碼在jni.h的44-51行,如下

typedef unsigned char   jboolean;       /* unsigned 8 bits */typedef signed char     jbyte;          /* signed 8 bits */typedef unsigned short  jchar;          /* unsigned 16 bits */typedef short           jshort;         /* signed 16 bits */typedef int             jint;           /* signed 32 bits */typedef long long       jlong;          /* signed 64 bits */typedef float           jfloat;         /* 32-bit IEEE 754 */typedef double          jdouble;        /* 64-bit IEEE 754 */

而jni層的參考型別則是下面這個樣子。

對於這些參考型別,c++和c的實現是不一樣的。如果是c++的話,所有參考型別派生自 jobject,如果使用 C 語言編寫的話,所有參考型別使用 jobject,其它參考型別使用 typedef 重新定義。同樣代碼也在jni.h中。這裡只給出c++繼承結構的部分。

class _jobject {};class _jclass : public _jobject {};class _jstring : public _jobject {};class _jarray : public _jobject {};class _jobjectArray : public _jarray {};class _jbooleanArray : public _jarray {};class _jbyteArray : public _jarray {};class _jcharArray : public _jarray {};class _jshortArray : public _jarray {};class _jintArray : public _jarray {};class _jlongArray : public _jarray {};class _jfloatArray : public _jarray {};class _jdoubleArray : public _jarray {};class _jthrowable : public _jobject {};
3. native 如何調用c

我們這裡的調用包括許多方面,如:

  • 調用靜態方法
  • 調用執行個體方法
  • 擷取欄位值
  • 修改欄位值
  • 構造對象
  • 等等

而要實現上面的一些功能,同樣要依靠jni.h的JNINativeInterface這個結構體,這裡有很多很多的方法,供我們使用來實現native 調用java層的功能。而調用的流程是這樣的:

  • 根據全限定名在jvm中找到想要的類
  • 從jclass中擷取到method、或者field
  • 執行擷取值、修改值、調用方法或者其他的操作
  • 釋放局部引用

舉個調用靜態方法的例子看看。

void callJavaStatic(JNIEnv *env,jobject jobj){  char* str = "call from c++";  jclass clazz = env->FindClass("com/example/cmake_demo/MainActivity");  if (clazz == NULL) {    LOGE("class is null");    return;  }  jmethodID method = env->GetStaticMethodID(clazz,"javaStaticMethod","(Ljava/lang/String;)V");  if (method == NULL) {    LOGE("not find method");  }  jstring  jstr = env->NewStringUTF(str);  env->CallStaticVoidMethod(clazz,method,jstr);  env->DeleteLocalRef(clazz);  env->DeleteLocalRef(jstr);}
3.1 如何找到類

很簡單,我們可以通過FindClass方法去尋找類。

jclass clazz = env->FindClass("com/example/cmake_demo/MainActivity");
3.2 如何擷取方法、或者欄位

大致為以下四種方法

 env->GetxxxField() env->GetStaticxxxField() env->GetMethodID() env->GetxxxMethodID()

上面沒有列出參數,但是仍然很明白,這裡就不多說了。

3.3 如何調用方法

這裡呢。大致分為以下四種:

  env->CallXXXMethod();  env->CallxxxMethodA();  env->CallxxxMethodV();  env->CallNonvirtualBooleanMethod()

同樣,我這裡沒給出方法的參數,同學們自己看jni.h吧

  • 調用方法(這裡的方法可能使靜態、也可能是非靜態)
  • 和上面的區別就在於對應的java層參數,在這裡以數組的形式傳進入
  • 和1的區別就是,以v(向量?)的形式傳進去,這裡我也不是很理解,希望知道的同學指點下。
  • 調用建構函式初始化一個對象,這個,馬上說道。
3.4 如何修改欄位的值

相信到這裡,大家猜都能猜出來,set 麼,這裡我就不叨叨了。

3.5 如何構造一個對象出來

有些情況下我們是需要構造出java層的對象的,那麼如何構造呢,我們有兩種辦法。

  • NewObject方法
  • CallNonvirtualxxMethod

先說第一種,NewObject方法,除了要求jclass參數之外,還要求jmethodid,以及java稱構造方法對應的參數。其他兩個還好,關鍵是這個jmethodID,這個在擷取的時候,方法名固定是< init >(md文法的原因,注意角括弧之間沒有空格),別問為什麼。

在來說說第二種,第二中使用時這樣的

  jobject  jo = env->AllocObject(clazz);  env->CallNonvirtualVoidMethod(jo,clazz,jmethodId,arg )
  • 第一行代碼 建立未初始化的對象,並分配記憶體
  • 第二行代碼,調用init那個方法(構造方法)進行初始化,注意,只能初始化一次。
4. 總結

現在我們明白了jni 和 java的資料類型映射關係,以及在jni層調用java層的方法。

Android JNI學習筆記(四)-資料類型映射以及native調用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.