1. 获得Java属性/设定Java属性值
取得了相应属性的jfieldID之后,就能够应用
Set<TYPE>FieldGet<TYPE>FieldSetStatic<TYPE>FieldGetStatic<TYPT>Field
等函数来对Java属性进行操作了。
类实例办法
Set/GetBooleanFieldSet/GetByteFieldSet/GetDoubleFieldSet/GetFloatFieldSet/GetIntFieldSet/GetLongFieldSet/GetShortFieldSet/GetObjectField
类静态方法
Set/GetStaticBooleanFieldSet/GetStaticByteFieldSet/GetStaticDoubleFieldSet/GetStaticFloatFieldSet/GetStaticIntFieldSet/GetStaticLongFieldSet/GetStaticShortFieldSet/GetStaticObjectField
怎么获取数组的属性呢?
能够应用GetObjectField来获取数组类型的属性。不过JNI提供了一系列办法获取数组的属性,后续介绍。
2. 案例
在C/C++中批改Java中的属性
package com.omg;public class TestNative { public int number; public native void sayHello();}
C++代码
jclass clazz_TestNative = env->GetObjectClass( obj);jfieldID id_number = env->GetFieldID(clazz_TestNative, "number", "I");jint number = env->GetIntFiled(obj, id_number);count << number << endl;env->SetIntField(obj, id_number, 100L);
3. Java办法调用
JNIEnv提供了泛滥的 Call<TYPE>Method 与 CallStatic<TYPE>Method,还有CallNonvirtual<TYPE>Method函数。须要通过GetMethodID获得相应办法的jmethodID来传入上述函数的参数中。
调用实例办法的三种模式
Call<TYPE>Method( jobject obj, jmethodID id, ...);Call<TYPE>MethodV( jobject obj, jmethodID id, va_list lst);Call<TYPE>MethodA( jobject obj, jmethodID id, jvalue* v);
第一种是最罕用的形式
第二种是当调用这个函数的时候,有一个指向参数表的va_list变量时应用(不罕用)
第三种是当调用这个函数的时候,有一个指向jvalue或者jvalue数组的指针时应用
调用静态方法的三种模式
CallStatic<TYPE>Method( jclass clazz, jmethodID id, ...);CallStatic<TYPE>MethodV( jclass clazz, jmethodID id, va_list lst);CallStatic<TYPE>MethodA( jclass clazz, jmethodID id, jvalue* v);
伪代码
java:public boolean function(int i, double d, char c){ //......}
C
env->CallBooleanMethod(obj, id_function, 100L, 1.11, L'3')jvalue * args = new jvalue[3];args[0].i = 100L;args[1].d = 3.44;args[2].c = L'3';env->CallBooleanMethod( obj, id_function, args);delete [] args;
4. 案例
在C/C++中代用Java中的办法
Java代码
package com.omg;public class TestNative { public max(double num1, double num2){ return num1 > num2 ? num1 : num2; }}
C++代码
jclass clazz_TestNative = env->GetObjectClass( obj );jmethodID id_max = env->GetMetodID( clazz_TestNative, obj, "(DD)D");jdouble maxVal = env->GetDoubleMethod(obj, id_max, 2.1, 3.14);cout << maxVal << endl;
5. CallNonvirtual<TYPE>Method
有如下Java代码
public class Father { public void function(){ System.out.println("Father function"); } } public class Child extends Father { public void function(){ System.out.println("Child function"); }}
想想这段Java代码调用的是哪个类的办法?
Father p = new Child();p.function();
如果想调用父类的function是没有方法的
有如下C++代码
class Father { public: void function(){ cout << "Father function" <<endl; }} class Child : public Father { public: void function(){ cout << "Child function" <<endl; }}
想想这段代码调用的是哪个类的成员函数?(调用的是父类的函数)
Father* p = new Child();p->function();
C++有虚函数的概念,批改一下父类加一个 virtual
class Father { public: virtual void function(){ cout << "Father function" <<endl; }}class Child : public Father { public: void function(){ cout << "Child function" <<endl; }}
再想想这段代码调用的是哪个类的成员函数?(调用的是子类的函数)
Father* p = new Child();p->function();
在Java语言中,所有的函数都是虚函数
在JNI中定义了CallNonvirtual<TYPE>Method就能实现子类对象调用父类办法的性能,如果想要调用一个对象的父类的办法,而不是子类的重写(over write)的办法的话,就能够应用CallNonVirtual<TYPE>Method
要应用CallNonVirtual<TYPE>Method,首先要获得父类及要调用的父类的办法的jmethodID。而后传入到这个函数就能通过子类对象调用被重写(over write)的父类的办法
5. 案例
package com.omg;public class Father { public void function() { System.out.println("Father function"); } }
package com.omg;public class Child extends Father { public void function() { System.out.println("Child function"); }}
测试
Java定义成员变量
public Father p = new Child();
C++代码
jclass clazz_TestNative = env->GetObjectClass( obj );jfieldID id_p = env->GetFieldID(clazz_TestNative, "p", "Lcom/omg/Father;");jobject p = env->GetObjectField(obj, id_p);jclass clazz_Father = env->FindClass( "Lcom/omg/Father;" );jmethodID id_Father_function = env->GetMethodID(clazz_Father, "function", "()V");env->CallVoidMethod(p, id_Father_function);env->CallNonvirtualVoidMethod(p, clazz_Father, id_Father_function);