之前实现了简单的jni入门实例, 这篇博客将主要介绍使用jni在c++调用java的属性和方法。
本地方法函数有两个参数,JNIEnv *和jobject,这两个参数非常重要
1.JNI数据类型
为了方便记忆和书写java数据类型与c++数据类型的对应,jni对数据进行封装。具体为下
2.获取java属性和方法
首先需要获取对应的java的类,jni专门定义了jclass类型来表示java的Class类,JNIEvn类中有几个函数取得jclass:
1.jclass FindClass(const char * clsName)----传入完整类名
2.jclass GetObjectClass(jobject obj)------传入类示例
3.jclass GetSuperClass(jclass obj)-------传入Class类
如: jclass string_class=evn->FindClass("java/lang/String")获取String类
得到java类后,访问java的属性或方法首先还要在本地代码中获取java属性的jfieldID和java方法的jmethodID才能进行使用。
使用JNIEvn的
1.GetFieldID/GetMethodID来获取非静态的属性和方法
2.GetStaticFieldID/GetStaticMethodID来获取静态的属性和方法
获取属性参数:(类,属性名,属性签名)
获取方法参数:(类,方法名,方法签名)
我们都知道java能对方法进行重载,为了准确获取对应的方法和属性,jni引入了Sign(签名),具体如下:
获取到java属性的ID后,就可获取和修改java的属性了,非静态属性可调用
Set/GetIntFieldSet/GetBooleanFieldSet/GetDoubleField
Set/GetFloatField
Set/GetLongField
Set/GetShortField
Set/GetObjectField-----------对应数组等
静态属性可调用
Set/GetStaticIntFieldSet/GetStaticBooleanFieldSet/GetStaticDoubleField
Set/GetStaticFloatField
Set/GetStaticLongField
Set/GetStaticShortField
Set/GetStaticObjectField
下面举实例
1.调用java属性
java代码如下,在本地方法sayhello里修改其属性score
package com.example; public class jni_test { //在本地方法sayHello里修改score的值 public native void sayHello(); public float score=99.9f; static{ System.loadLibrary("NativeCode"); } public static void main(String[] args) { jni_test temp=new jni_test(); temp.sayHello(); //输出temp的score属性的值 System.out.println("score: "+temp.score); } }
c++本地方法实现的代码:
#include"com_example_jni_test.h" #include<iostream> using namespace std; JNIEXPORT void JNICALL Java_com_example_jni_1test_sayHello(JNIEnv * evn, jobject obj) { //获取java的Class--sayHello方法是非静态方法,所以此时obj是调用这个函数的实例,即java中的实例temp jclass my_class=evn->GetObjectClass(obj); //jclass my_class=evn->FindClass("com/example/jni_test");也可以获取Class //获取java的score属性的FieldID jfieldID score_id=evn->GetFieldID(my_class,"score","F");//(类,属性名.签名) //根据FieldID获取属性 jfloat score=evn->GetFloatField(obj,score_id);//(实例对象,属性ID) //修改java的temp的score的值 evn->SetFloatField(obj,score_id,88.8); }
编译生成dll加入PATH即可.
运行结果为:
至此,成功获取java对象的属性并修改其属性的值
2.调用java方法
在本地方法里调用Max_num,输出最大值
java代码:
package com.example; public class jni_test { //在本地方法sayHello里调用Max_num方法 public native void sayHello(); //返回最大值 public void Max_num(int ok,int ok1) { if(ok>ok1) System.out.println("最大值是: "+ok); else System.out.println("最大值是: "+ok1); } static{ System.loadLibrary("NativeCode"); } public static void main(String[] args) { jni_test temp=new jni_test(); temp.sayHello();//输出最大值 } }
本地方法C++实现
#include"com_example_jni_test.h" #include<iostream> using namespace std; JNIEXPORT void JNICALL Java_com_example_jni_1test_sayHello(JNIEnv * evn, jobject obj) { //获取java的Class--sayHello方法是非静态方法,所以此时obj是调用这个函数的实例,即java中的实例temp jclass my_class=evn->GetObjectClass(obj); //jclass my_class=evn->FindClass("com/example/jni_test");也可以获取Class //获取java的Max_num方法的ID jmethodID max_id=evn->GetMethodID(my_class,"Max_num","(II)V");//(类,属性名.签名) //调用Max_num方法--Call<type>Method--type函数返回值 evn->CallVoidMethod(obj,max_id,100,123);//(对象,方法ID,参数...) }
运行结果:
相关推荐
1)传递基础数据类型 2)传递返回字符串类型 3)传递返回数组 4)Native层操作java类属性 5)Native层回调java方法 6)传递返回一个java类 7)Native线程回调java方法 8)Native调用第三方库
6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用...
10.2 增添属性和有用的接口 10.2.1 通过FilterInputStream从InputStream里读入数据 10.2.2 通过FilterOutputStream向OutputStream里写入数据 10.3 本身的缺陷:RandomAccessFile 10.4 File类 10.4.1 目录列表器 ...
6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用...
10.2 增添属性和有用的接口 10.2.1 通过FilterInputStream从InputStream里读入数据 10.2.2 通过FilterOutputStream向OutputStream里写入数据 10.3 本身的缺陷:RandomAccessFile 10.4 File类 10.4.1 目录列表器 ...
10.2 增添属性和有用的接口 10.2.1 通过FilterInputStream从InputStream里读入数据 10.2.2 通过FilterOutputStream向OutputStream里写入数据 10.3 本身的缺陷:RandomAccessFile 10.4 File类 10.4.1 目录列表器 ...
10.2 增添属性和有用的接口 10.2.1 通过FilterInputStream从InputStream里读入数据 10.2.2 通过FilterOutputStream向OutputStream里写入数据 10.3 本身的缺陷: 10.4 File类 10.4.1 目录列表器 10.4.2 检查与创建...
10.2 增添属性和有用的接口 10.2.1 通过FilterInputStream从InputStream里读入数据 10.2.2 通过FilterOutputStream向OutputStream里写入数据 10.3 本身的缺陷:RandomAccessFile 10.4 File类 10.4.1 目录列表器 ...
10.2 增添属性和有用的接口 10.2.1 通过FilterInputStream从InputStream里读入数据 10.2.2 通过FilterOutputStream向OutputStream里写入数据 10.3 本身的缺陷:RandomAccessFile 10.4 File类 10.4.1 目录列表器 ...
robusta — Rust和Java之间的轻松互操作 该库提供了一个过程宏,可以更轻松地在Rust中编写与JNI兼容的代码。 它可以执行Rust-y输入和输出类型的自动转换(请参阅)。 [ dependencies ] robusta_jni = " 0.1 " 用法...
10.2 增添属性和有用的接口 10.2.1 通过FilterInputStream从InputStream里读入数据 10.2.2 通过FilterOutputStream向OutputStream里写入数据 10.3 本身的缺陷:RandomAccessFile 10.4 File类 10.4.1 目录列表器 ...
10.2 增添属性和有用的接口 10.2.1 通过FilterInputStream从InputStream里读入数据 10.2.2 通过FilterOutputStream向OutputStream里写入数据 10.3 本身的缺陷:RandomAccessFile 10.4 File类 10.4.1 目录列表器...
它根据系统属性os.name和os.arch的值规范化操作系统和体系结构,然后在类路径上查找 zip 存档${libName}-${os}-${arch}并提取其内容到一个临时目录。 临时目录和存档中找到的任何子目录都被添加到java.library.path...
2.3.2 Java的native函数和总结 2.4 JNI层MediaScanner的分析 2.4.1 注册JNI函数 2.4.2 数据类型转换 2.4.3 JNIEnv介绍 2.4.4 通过JNIEnv操作jobject 2.4.5 jstring介绍 2.4.6 JNI类型签名介绍 2.4.7 垃圾回收 2.4.8 ...
10.2 增添属性和有用的接口 10.2.1 通过FilterInputStream从InputStream里读入数据 10.2.2 通过FilterOutputStream向OutputStream里写入数据 10.3 本身的缺陷:RandomAccessFile 10.4 File类 10.4.1 目录列表器 ...
但是其中还是有一些问题,如CMYK图片的操作,可喜的是这种图片非常之少,涉及到了很多的图形编程,Java在这一块不是太强(特别是JDK1.4,图形处理有很多BUG),能使用JNI接口来调用其他语言处理图形是最好不过了。
如果文件打开看不到右边的内容,是因为你的操作系统为了安全对下载的chm文件进行了锁定,只需要在打开前右键单击该chm文件选择“属性”,然后在“常规”选项卡的下方单击“解除锁定”按钮就可以了。如果还是不能看,...
10.2 增添属性和有用的接口 10.2.1 通过FilterInputStream从InputStream里读入数据 10.2.2 通过FilterOutputStream向OutputStream里写入数据 10.3 本身的缺陷:RandomAccessFile 10.4 File类 10.4.1 目录列表器 ...
10.2 增添属性和有用的接口 10.2.1 通过FilterInputStream从InputStream里读入数据 10.2.2 通过FilterOutputStream向OutputStream里写入数据 10.3 本身的缺陷:RandomAccessFile 10.4 File类 10.4.1 目录列表器 ...