一、前言
在NDK
程式設計時,當我們在Java
層呼叫一個原生方法時,不可避免地要涉及到引數的傳遞,今天,我們就來一起學習一下如何在原生方法中解析從Java
層傳遞過來的資料。
二、引數分類
我們根據Java
當中的資料型別,將傳遞的引數分為以下三類。
2.1 基本資料型別
對於Java
,其基本資料型別有八類,這八類基本資料型別在分別和JNI
中的jxxx
八類基本資料型別相對應,對應關係為:
jni.h
和jni_md.h
標頭檔案,會發現jxxx
其實是對於C/C++
中基本資料型別的巨集定義:
# (1) jint
typedef int jint;
# (2) jlong
#ifdef _LP64
typedef long jlong;
#else
typedef long long jlong;
#endif
# (3) jbyte
typedef signed char jbyte;
# (4) jboolean
typedef unsigned char jboolean;
# (5) jchar
typedef unsigned short jchar;
# (6) jshort
typedef short jshort;
# (7) jfloat
typedef float jfloat;
# (8) jdouble
typedef double jdouble;
複製程式碼
這八類基本資料型別的特點是:我們可以在JNI
的原生函式中直接訪問。
2.2 引用型別
對於Java
當中的引用型別,它們對映到JNI
中,都是作為jobject
的子類:
jclass
:Class
位元組碼物件jthrowable
:異常jstring
:字串jarray
:陣列,根據陣列元素型別的不同,jarray
又衍生出九種子類,也就是八種基本資料型別加上引用型別。
它們在jni.h
中的定義為:
# (1)
class _jobject {};
# (1)
class _jclass : public _jobject {};
# (2)
class _jthrowable : public _jobject {};
# (3)
class _jstring : public _jobject {};
# (4)
class _jarray : public _jobject {};
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 _jobjectArray : public _jarray {};
複製程式碼
和基本資料型別不同,對於引用型別的訪問需要通過JNI
提供的方法。
三、例項講解
下面我們用一個例項來講解每一種型別的訪問方式。
3.1 基本資料型別
從上面的程式碼可以看出,從Java
方法到Native
方法,除了前面兩個引數,都是一一對應的,前面兩個引數的含義為:
JNIEnv*
:第一個引數是一個指向JVM
函式表的指標,函式表中的每一個入口指向一個JNI
函式,我們可以通過這些函式去訪問JVM
中的資料結構。jobject/jclass
:第二個引數的型別取決於在Java
中Native
方法的型別:- 如果是一個普通方法,那麼引數型別為
jobject
,引數含義為呼叫Native
方法的例項。 - 如果是一個
static
方法,引數型別為jclass
,引數含義為呼叫Native
方法的Class
物件。
3.2 引用型別
對於所有的引用型別,JNI
將Java
中的所有物件當作一個C
指標傳遞到本地方法中,這個指標指向JVM
中的內部資料結構,而對於該資料結構的訪問需要通過第一個引數JNIEnv*
函式表所提供的函式來訪問,下面,我們就來介紹這四種型別的基本訪問。
3.2.1 字串
對於字串,我們可以分為以下幾類: **(1) **