IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> JNI 回调实例方法与静态方法 -> 正文阅读

[移动开发]JNI 回调实例方法与静态方法

JNI 回调实例方法与静态方法

在上一篇中介绍了JNI静态变量。本文是JNI系列的第七篇,介绍JNI中的如何在Native代码调用Java中的方法和静态方法。

系列文章的大纲如下:

JNI 回调实例方法与静态方法

在Native中调用实例方法和静态方法与访问实例变量和静态变量的方法差不多。

只不过现在需要获取的是方法的ID,不再是变量的ID。使用jmethodID表示。

// 获取名字为name的成员方法的ID,其中sig为类型签名
jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig);

关于类型签名,可以参考JNI 基本类型

同样获取静态方法的接口:

// 获取名字为name的静态成员方法的ID,其中sig为类型签名
jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig);

拿到方法的ID之后,就可以使用下面的函数来调用方法了:

// 调用实例方法
NativeType Call<type>Method(JNIEnv *env, jobject obj, jmethodID methodID, ...);
NativeType Call<type>MethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
NativeType Call<type>MethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args);

其中:

Call<type>Method RoutinesNativeType
CallVoidMethod()jobject
CallObjectMethod()jobject
CallBooleanMethod()jboolean
CallByteMethod()jbyte
CallCharMethod()jchar
CallShortMethod()jshort
CallIntMethod()jint
CallLongMethod()jlong
CallFloatMethod()jfloat
CallDoubleMethod()jdouble

Call<type>Method()Call<type>MethodA()Call<type>MethodV()之前的区别在于传递参数的形式上的区别。
具体参见下面的实例。

关于jvalue的定义可以看这里JNI String

// 调用静态方法
NativeType CallStatic<type>Method(JNIEnv *env, jobject obj, jmethodID methodID, ...);
NativeType CallStatic<type>MethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
NativeType CallStatic<type>MethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args);

其中:

CallStatic<type>Method RoutinesNativeType
CallStaticVoidMethod()jobject
CallStaticObjectMethod()jobject
CallStaticBooleanMethod()jboolean
CallStaticByteMethod()jbyte
CallStaticCharMethod()jchar
CallStaticShortMethod()jshort
CallStaticIntMethod()jint
CallStaticLongMethod()jlong
CallStaticFloatMethod()jfloat
CallStaticDoubleMethod()jdouble

通过下面的实例来加深一下理解。

实例

我们来看一个实例。

这次我们要换一个例子来看了,

package myjni;

public class JNICallbackMethod {
    static {
        System.loadLibrary("hello");
    }

    public void callback() {
        System.out.println("callback()");
    }

    public double add(double a, double b) {
        return a + b;
    }

    public static void say(String name) {
        System.out.println("hello, " + name);
    }

    public native void testNative();

    public static void main(String[] args) {
        new JNICallbackMethod().testNative();
    }
}

在Java代码中实现的成员方法callback()add()和静态方法say()是会被在native的方法
testNative()中调用的。

如果还不清楚如果生成头文件请参考JNI简介

生成头文件myjni_JNICallbackMethod.h的签名为:

/*
 * Class:     myjni_JNICallbackMethod
 * Method:    testNative
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_myjni_JNICallbackMethod_testNative
(JNIEnv *, jobject);

实现函数Java_myjni_JNICallbackMethod_testNative


JNIEXPORT void JNICALL Java_myjni_JNICallbackMethod_testNative(JNIEnv *env, jobject obj) {
  jclass clazz = env->GetObjectClass(obj);
  if (clazz == NULL) {
    return;
  }
  
  // callback
  jmethodID midCallback = env->GetMethodID(clazz, "callback", "()V");
  if (midCallback == NULL) {
    return;
  }
  
  env->CallVoidMethod(obj, midCallback);
  
  // add
  jmethodID midAdd = env->GetMethodID(clazz, "add", "(DD)D");
  if (midAdd == NULL) {
    return;
  }
  jdouble result = env->CallDoubleMethod(obj, midAdd, 1.1, 2.2);
  std::cout << "1.1 + 2.2 = " << result << std::endl;
  
  jvalue values[2];
  values[0].d = 11.1;
  values[1].d = 22.2;
  result = env->CallDoubleMethodA(obj, midAdd, values);
  std::cout << values[0].d << " + " << values[1].d << " = "
            << result << std::endl;
  
  // add say
  jmethodID midSay = env->GetStaticMethodID(clazz, "say", "(Ljava/lang/String;)V");
  if (midSay == NULL) {
    return;
  }
  
  jstring name = env->NewStringUTF("Furzoom");
  env->CallStaticVoidMethod(clazz, midSay, name);
}

编译生成动态库,并运行Java程序得到输出:

callback()
1.1 + 2.2 = 3.3
11.1 + 22.2 = 33.3
hello, Furzoom

vx搜:极客Furzoom,关注获取第一手资料。

本文完。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-11-20 18:30:36  更:2021-11-20 18:31:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:56:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码