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特别篇中多介绍几个使用案例

猜你喜欢

转载自blog.csdn.net/qq_32648731/article/details/106398190