返回介绍

2.4 JNIEnv 类型中方法的使用

发布于 2024-10-10 22:32:14 字数 4284 浏览 0 评论 0 收藏 0

前面说到 JNIEnv 类型,下面通过例子来看一下这些方法的使用。第一个例子是在 Java 代码中定义一个属性,然后再从 C++代码中将其设置成另外的值,并且输出来。

2.4.1 native 中获取方法的 Id

先来看一下 Java 代码:

再来看一下 C++代码:

编译成功后,在 Eclipse 运行后的结果如图 2-24 所示。

图 2-24 运行成功效果图

第一个 0 是在 C++代码中的 cout<<number<<endl。

第二个 100 是在 Java 中的 System.out.println(jniDemo.number)。

JNIEnv 提供了众多的 Call<Type>Method 和 CallStatic<Type>Method,还有 CallNonvirtual<Type>Method 函数,需要通过 GetMethodID 取得相应方法的 jmethodID 来传入到上述函数的参数中。

调用示例方法的三种形式如下:

第一种是最常用的方式。第二种是当调用这个函数的时候有一个指向参数表的 va_list 变量时使用的(很少使用)。第三种是当调用这个函数的时候有一个指向 jvalue 或 jvalue 数组的指针时用的。

jvalue 在 jni.h 头文件中定义是一个 union 联合体,在 C/C++中,union 可以存放不同类型的值,但是当你给其中一个类型赋值之后,这个 union 就是这种类型了,比如你给 jvalue 中的 s 赋值的话,jvalue 就变成了 jshort 类型了,所以可以定义一个 jvalue 数组(这样就可以包含多种类型的参数了)传递到方法中,如下所示:

假如现在 Java 中有这样的一个方法:

1)在 C++中使用第一种方式调用 function 方法:

obj 是方法 funtion 的对象。id_function 是方法 function 的 id,可以通过 GetMethodID()方法获取。然后就是对应的参数,这和 Java 中的可变参数类似。最后一个 char 类型的参数 L'a'为什么前面要加一个 L 呢?原因是 Java 中的字符是 Unicode 双字节的,而 C++中的字符是单字节的,所以要变成宽字符,即前面加一个 L。

2)在 C++中使用第三种方式调用 function 方法:

例子:C++中调用 Java 中的方法。

Java 代码如下:

这时候用 javap 获取 max 方法的签名,如下所示。

max 方法的签名是(DD)D。在 C++中的代码如下:

编译成动态文件后,到 Eclipse 中执行 sayHello 方法,运行结果如图 2-25 所示。

图 2-25 运行成功效果图

可见,成功地输出了最大值。

2.4.2 Java 和 C++中的多态机制

JNIEnv 中有一个特殊的方法 CallNonvirtual<Type>Method,如下所示:

首先来了解一下,上面调用的 function 是子类的 function 方法,但是在 C++中就不一样了:

这段 C++代码中执行的是父类的 function 方法,如果想执行子类的 function 方法怎么办呢?就需要将父类的 function 方法定义成 virtual 虚函数:

所以,C++和 Java 对于继承后执行的是父类还是子类的方法是有区别的,在 Java 中所有的方法都是虚拟的,所以总是调用子类的方法,因此 CallNonVirtual<Type>Method 方法就出来了,这个方法可以帮助调用 Java 中父类的方法。

在 JNI 中定义的 CallNonvirtual<Type>Method 能够实现子类对象调用父类方法的功能,如果想要调用一个对象的父类方法,而不是子类的方法,就可以使用 CallNonvirtual<Type>Method。要使用它,首先要获得父类及其要调用的父类方法的 jmethodID,然后传入到这个函数就能通过子类对象调用被覆写的父类方法了。

例如:在 Java 中定义 Father 类:

定义一个子类 Child,继承 Father 类,重写父类中的 function 方法:

在 JNIDemo 代码,定义 Father 类型的属性:

再来看一下 C++中的代码:

编译成功.dll 文件,回到 Eclipse 中运行结果参如图 2-26 所示。

图 2-26 运行结果

其中:

·Child:function 是调用 env->CallVoidMethod(...)方法的。

·Father:function 是调用 env->CallNonvirtualMethod(...)方法的。

这样就能够控制到底调用哪个类的 function 方法了。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文