【Android NDK 开发】JNI 方法解析 ( C/C++ 调用 Java 方法 | 函数签名 | 调用对象方法 | 调用静态方法 )(二)

简介: 【Android NDK 开发】JNI 方法解析 ( C/C++ 调用 Java 方法 | 函数签名 | 调用对象方法 | 调用静态方法 )(二)

VII . 反射获取类静态方法 ( GetStaticMethodID )


函数原型 : 通过 jclass 对象 , 方法名称 , 和 方法签名 , 获取 Java 类对象对应的方法 ID 即 jmethodID 类型变量 ;


返回值 : Java 类对象对应的方法 ID ( jmethodID 类型变量 )


参数 :


jclass clazz : 要获取的 Java 对象方法对应的 Java 类对象 ;
const char* name : 方法名称 ;
const char* sig : 方法签名 , 使用 javap 命令获得 ;
struct _JNIEnv {
    /* _JNIEnv  结构体中封装了 JNINativeInterface 结构体指针 */
    const struct JNINativeInterface* functions;
    ...
    // 最终 调用的 还是 JNINativeInterface 结构体中封装的 GetStaticMethodID 方法
    jmethodID GetStaticMethodID(jclass clazz, const char* name, const char* sig)
    { return functions->GetStaticMethodID(this, clazz, name, sig); }
    ...
}



2 . 代码示例 : 获取 Student 类的 getAge 方法 ;


student_class 是 Student 类对应的 C/C++ 中的 jclass 类型变量 ,
“logInfo” 是方法名称 ,
“(Ljava/lang/String;)V” 是方法签名 , 左侧的括号是参数列表类型签名 , 括号右的 V 是返回值类型 void ;
extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_jni_MainActivity_jniObjectTest(JNIEnv *env, jobject instance, jobject student) {
    ...
  //1 . 获取 Java 对应的 Class 对象
    jclass student_class = env->GetObjectClass(student);
    //2 . 获取 Student 的 public static void logInfo(String info) 方法
    //  注意这里要使用 GetStaticMethodID 方法反射该静态方法
    jmethodID method_logInfo = env->GetStaticMethodID(student_class, "logInfo" , "(Ljava/lang/String;)V");
  ...
}




VIII . 调用 Java 对象方法 ( CallXxxMethod )


注意 : 返回值和参数必须 都是 Java 类型 ;


函数原型 : 通过 Java 对象 , Java 方法 ID , 及根据函数签名传入的 参数列表 ( 可变参数 ) , 反射调用该 Java 对象的方法 ;


返回值 : Void , 注意这里的返回值可以是 8 种 基本数据类型 , jboolean , jbyte , jshort 等类型 , 也可以是引用类型 jobject 类型 , 只有这 10 种返回类型 , 没有其它类型 ; ( 注意 : 返回值 都是 Java 类型 )


参数 :


jobject obj : 要获取的 Java 对象方法对应的 Java 类对象 ;
jmethodID methodID : 方法 ID ;
… : 可变参数 , 方法的参数 ( 注意 : 参数 必须 都是 Java 类型 ) ;
struct _JNIEnv {
    /* _JNIEnv  结构体中封装了 JNINativeInterface 结构体指针 */
    const struct JNINativeInterface* functions;
    ...
    // 最终 调用的 还是 JNINativeInterface 结构体中封装的 CallVoidMethod 方法
    void CallVoidMethod(jobject obj, jmethodID methodID, ...)
    {
        va_list args;
        va_start(args, methodID);
        functions->CallVoidMethodV(this, obj, methodID, args);
        va_end(args);
    }
    ...
}



2 . 所有 Java 方法调用返回值类型 :


 

jobject     (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);
    jobject     (*CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jobject     (*CallObjectMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
    jboolean    (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...);
    jboolean    (*CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jboolean    (*CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
    jbyte       (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...);
    jbyte       (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jbyte       (*CallByteMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
    jchar       (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...);
    jchar       (*CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jchar       (*CallCharMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
    jshort      (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...);
    jshort      (*CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jshort      (*CallShortMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
    jint        (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
    jint        (*CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jint        (*CallIntMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
    jlong       (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...);
    jlong       (*CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jlong       (*CallLongMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
    jfloat      (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...);
    jfloat      (*CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jfloat      (*CallFloatMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
    jdouble     (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...);
    jdouble     (*CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    jdouble     (*CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
    void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
    void        (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list);
    void        (*CallVoidMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);



3 . 代码示例 : 调用 Student 类的 getAge 方法 ;


student 是 Student 类对象 ,
“method_getAge” 是方法 ID
由于没有参数 , 因此后面的可变参数列表为空 ;
extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_jni_MainActivity_jniObjectTest(JNIEnv *env, jobject instance, jobject student) {
    ...
  //1 . 获取 Java 对应的 Class 对象
    jclass student_class = env->GetObjectClass(student);
    //2 . 获取 Student 的 public static void logInfo(String info) 方法
    //  注意这里要使用 GetStaticMethodID 方法反射该静态方法
    jmethodID method_logInfo = env->GetStaticMethodID(student_class, "logInfo" , "(Ljava/lang/String;)V");
  //3 . 调用 Student 的 public int getAge() 方法
    jint age = env->CallIntMethod(student, method_getAge);
  ...
}




IX . 调用 Java 类静态方法 ( CallStaticXxxMethod )


注意 : 返回值和参数必须 都是 Java 类型 ;


函数原型 : 通过 Java 类对象 ( Class 对象 对应 C/C++ jclass 类型对象 ) , Java 方法 ID , 及根据函数签名传入的 参数列表 ( 可变参数 ) , 反射调用该 Java 对象的方法 ;


返回值 : Void , 注意这里的返回值可以是 8 种 基本数据类型 , jboolean , jbyte , jshort 等类型 , 也可以是引用类型 jobject 类型 , 只有这 10 种返回类型 , 没有其它类型 ; ( 注意 : 返回值 都是 Java 类型 )


参数 :


jobject obj : 要获取的 Java 对象方法对应的 Java 类对象 ;
jmethodID methodID : 方法 ID ;
… : 可变参数 , 方法的参数 ( 注意 : 参数 必须 都是 Java 类型 ) ;
struct _JNIEnv {
    /* _JNIEnv  结构体中封装了 JNINativeInterface 结构体指针 */
    const struct JNINativeInterface* functions;
    ...
    // 最终 调用的 还是 JNINativeInterface 结构体中封装的 CallStaticVoidMethodV 方法
    void CallStaticVoidMethod(jclass clazz, jmethodID methodID, ...)
    {
        va_list args;
        va_start(args, methodID);
        functions->CallStaticVoidMethodV(this, clazz, methodID, args);
        va_end(args);
    }
    ...
}


2 . 所有 Java 方法调用返回值类型 :


 

jobject     (*CallStaticObjectMethod)(JNIEnv*, jclass, jmethodID, ...);
    jobject     (*CallStaticObjectMethodV)(JNIEnv*, jclass, jmethodID, va_list);
    jobject     (*CallStaticObjectMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
    jboolean    (*CallStaticBooleanMethod)(JNIEnv*, jclass, jmethodID, ...);
    jboolean    (*CallStaticBooleanMethodV)(JNIEnv*, jclass, jmethodID,
                        va_list);
    jboolean    (*CallStaticBooleanMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
    jbyte       (*CallStaticByteMethod)(JNIEnv*, jclass, jmethodID, ...);
    jbyte       (*CallStaticByteMethodV)(JNIEnv*, jclass, jmethodID, va_list);
    jbyte       (*CallStaticByteMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
    jchar       (*CallStaticCharMethod)(JNIEnv*, jclass, jmethodID, ...);
    jchar       (*CallStaticCharMethodV)(JNIEnv*, jclass, jmethodID, va_list);
    jchar       (*CallStaticCharMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
    jshort      (*CallStaticShortMethod)(JNIEnv*, jclass, jmethodID, ...);
    jshort      (*CallStaticShortMethodV)(JNIEnv*, jclass, jmethodID, va_list);
    jshort      (*CallStaticShortMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
    jint        (*CallStaticIntMethod)(JNIEnv*, jclass, jmethodID, ...);
    jint        (*CallStaticIntMethodV)(JNIEnv*, jclass, jmethodID, va_list);
    jint        (*CallStaticIntMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
    jlong       (*CallStaticLongMethod)(JNIEnv*, jclass, jmethodID, ...);
    jlong       (*CallStaticLongMethodV)(JNIEnv*, jclass, jmethodID, va_list);
    jlong       (*CallStaticLongMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
    jfloat      (*CallStaticFloatMethod)(JNIEnv*, jclass, jmethodID, ...);
    jfloat      (*CallStaticFloatMethodV)(JNIEnv*, jclass, jmethodID, va_list);
    jfloat      (*CallStaticFloatMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
    jdouble     (*CallStaticDoubleMethod)(JNIEnv*, jclass, jmethodID, ...);
    jdouble     (*CallStaticDoubleMethodV)(JNIEnv*, jclass, jmethodID, va_list);
    jdouble     (*CallStaticDoubleMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
    void        (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);
    void        (*CallStaticVoidMethodV)(JNIEnv*, jclass, jmethodID, va_list);
    void        (*CallStaticVoidMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);


目录
相关文章
|
3天前
|
存储 编译器 C语言
c++的学习之路:5、类和对象(1)
c++的学习之路:5、类和对象(1)
19 0
|
3天前
|
C++
c++的学习之路:7、类和对象(3)
c++的学习之路:7、类和对象(3)
19 0
|
4天前
|
Java 关系型数据库 MySQL
Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
【4月更文挑战第12天】Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
28 3
|
1天前
|
Java
Java 与垃圾回收有关的方法
Java 与垃圾回收有关的方法
|
1天前
|
存储 Java 测试技术
一文搞清楚Java中的方法、常量、变量、参数
在JVM的运转中,承载的是数据,而数据的一种变现形式就是“量”,量分为:**常量与变量**,我们在数学和物理学中已经接触过变量的概念了,在Java中的变量就是在程序运行过程中可以改变其值的量。
4 0
|
2天前
|
编译器 C++
【C++基础(八)】类和对象(下)--初始化列表,友元,匿名对象
【C++基础(八)】类和对象(下)--初始化列表,友元,匿名对象
|
6天前
|
存储 Java
Java动态转发代理IP的实现方法
Java动态转发代理IP的实现方法
22 11
|
2天前
|
设计模式 Java C++
【C++高阶(八)】单例模式&特殊类的设计
【C++高阶(八)】单例模式&特殊类的设计
|
6天前
|
存储 安全 C语言
【C++】string类
【C++】string类
|
存储 编译器 Linux
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”