Android NDK開發基礎篇(二)

此係列記錄Android NDK基礎開發知識,在Android NDK開發基礎篇(一)中介紹了NDK、JNI以及關係,包括AS創建JNI的項目及第一個函數解析,

目的

  1. Java類型和native類型的映射關係
  2. jobject
  3. jclass
  4. JNIEnv 的基本使用

用於參數解析:

Java_com_kpa_jnijavademo_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject obj/* this */) {
    return env->NewStringUTF(hello.c_str());
}

一、Java類型和native類型的映射關係

Java類型 本地類型 JNI定義的別名
int long jint/jsize
short short jshort
long _int64 jlong
float float jfloat
double double jdouble
byte signed char jbyte
boolean unsigned char jboolean
char unsigned char jchar
Object _jobject* jobject

本地類型指的是在C/C++中的使用,JNI定義的別名是C/C++在JNI中的使用,不需要多記,後續回經常出現

二、 jobject

jobject 表示的是Java中的Object類型,在參數中有兩個不同的意義需要知道

  • native方法是static 修飾的: 代表native方法的類的class對象的實例
  • native方法不是static 修飾的:表示native方法的實例

三、jclass

jclass 表示Java的中的Class類

在下面的JNIEnv 中會解釋jclass 在C/C++中的集中獲取方法

四、 JNIEnv

JNIEnv 類型在native 中實際代表了Java在native中的Java環境 ,通過JNIEnv*指針可以對Java端的代碼進行操作,爲什麼JNI開發中首先要了解對Java的操作呢?

JNI作爲Java和C/C++的連接橋樑,自然能在C/C++中操作Java的對象,最起碼我們在C/C++中的一系列操作完成之後,將結果返回給Java就需要用到Java操作,以此問題還有很多。

既然是代表了Java環境,那首先有這幾個概念需要了解一下:

  1. 對象
  2. 屬性
  3. 方法

這是最起碼操作一個Java對象應該具備的要素

4.1在native中創建一個Java對象

Newobject

/**
*jclass : Class 對象(後續解釋怎麼獲取一個class對象)
*methodID: 方法ID
**/
jobject NewObject(jclass clazz, jmethodID methodID, ...)
    {
        va_list args;
        va_start(args, methodID);
        jobject result = functions->NewObjectV(this, clazz, methodID, args);
        va_end(args);
        return result;
    }

jmethodID 在JNI中表示一個指向method的指針,創建對象時的method哪裏來呢? 沒錯就是構造方法

爲了後續更好的理解 先看一下jclass 的獲取方法

4.2 JNIEnv 中獲取jclass 的方法

  • FindClass
// 通過類的全名獲取class 對象
 jclass FindClass(const char* name)
    { return functions->FindClass(this, name); }

eg:

// 獲取Java中Date 對象的Class對象
jclass date_clazz = env->FindClass("java/util/Date");
  • GetObjectClass
// 通過native方法中的jobject對象獲取Class 對象
jclass GetObjectClass(jobject obj)
    { return functions->GetObjectClass(this, obj); }

eg:

Java_com_kpa_jnijavademo_JNIDemo_sayHello(JNIEnv *env, jobject thiz) {
// 根據native sayHello方法中jobject 的class 對象
    jclass jniDemo = env->GetObjectClass(thiz);
    }
  • GetSuperClass
//根據jclass 可以獲取他的父類的jclass 對象
jclass GetSuperclass(jclass clazz)
    { return functions->GetSuperclass(this, clazz); }

4.3 JNI獲取jmethod、jfieldID

GetMethodID/GetStaticMethodID

/**
* clazz 所在class 對象
* name: 方法名稱
* sig: 方法簽名(變量和方法在JNI中都是有簽名的)
**/
jmethodID GetMethodID(jclass clazz, const char* name, const char* sig)
    { return functions->GetMethodID(this, clazz, name, sig); }
jmethodID GetStaticMethodID(jclass clazz, const char* name, const char* sig)
    { return functions->GetStaticMethodID(this, clazz, name, sig); }


GetFieldID/GetStaticFieldID

jfieldID GetFieldID(jclass clazz, const char* name, const char* sig)
    { return functions->GetFieldID(this, clazz, name, sig); }

jfieldID GetStaticFieldID(jclass clazz, const char* name, const char* sig)
    { return functions->GetStaticFieldID(this, clazz, name, sig); }

通過javap命令查看類中的屬性和方法的簽名

javap -s -p XXX.class

eg:

public class com.kpa.jnijavademo.Demo {
  public int a;
    descriptor: I
  public com.kpa.jnijavademo.Demo();
    descriptor: ()V //構造方法簽名

  public int add(int, int);
    descriptor: (II)I

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
}

I、()V、(II)I都是簽名

eg:

void createObj1(JNIEnv *env) {// native 創建Java對象
// 獲取Java中的Date的Class對象
    jclass date_clazz = env->FindClass("java/util/Date");
    // 獲取構造方法的ID 構造方法名稱始終是<init>
    jmethodID mid_date = env->GetMethodID(date_clazz, "<init>", "()V");
    // 生成Date對象
    jobject date_obj = env->NewObject(date_clazz, mid_date);
    jmethodID get_time_id = env->GetMethodID(date_clazz, "getTime", "()J");
    jlong time = env->CallLongMethod(date_obj, get_time_id);
    printf("時間 ==== %I64d", time);
}

然後看一下上面4.1中NewObject創建一個對象

eg:

// 獲取Java中的Date的Class對象
    jclass date_clazz = env->FindClass("java/util/Date");
    // 獲取構造方法的ID 構造方法名稱始終是<init>
    jmethodID mid_date = env->GetMethodID(date_clazz, "<init>", "()V");

4.4

到此爲止,介紹了JNI中如果獲取對象的Class 對象,創建對象,以及獲取方法、屬性等功能。

在Android NDK特別篇中多介紹幾個使用案例

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章