在取得了相应属性的jfieldID之后就可以用Set<TYPE>Field,Get<TYPE>Field,SetStatic<TYPE>Field,GetStatic<TYPE>Field等函数来对JAVA属性进行操作了
Set/GetBooleanField
Set/GetByteField
Set/GetShortField
Set/GetIntField
Set/GetLongField
Set/GetFloatField
Set/GetDoubleField
Set/GetObjectField
Set/GetStaticBooleanField
Set/GetStaticByteField
Set/GetStaticShortField
Set/GetStaticIntField
Set/GetStaticLongField
Set/GetStaticFloatField
Set/GetStaticDoubleField
Set/GetStaticObjectField
下面举例说明
//定义一个class package test.jni; import java.util.Date; public class TestJative{ public native void sayHello(); public int number = 10; public static void main(String[] args){ System.loadLibrary("nativeCode"); TestNative tst = new TestNative(); tst.sayHello(); System.out.println(number); } } //对于C语言 JNIEXPORT void JNICALL Java_test_java_TestNative_sayHello(JNIEnv* env ,JObject* obj){ jclass clazz_TestNative = env->GetObjectClass(obj); jfieldID id_member = env->GetFieldID(clazz, "number", "I"); jint number = env->GetIntField(obj, id_member); cout << number << endl; env->SetIntField(obj, id_member, 20L); } TestNative 运行结果: 10 20
JNIEnv提供了众多的Call<TYPE>Method跟CallStatic<TYPE>Method跟CallNonvirtual<TYPE>Method函数。需要通过GetMethodID取得相应方法的jmethodID来传入到上述的参数中
例 :
java:
boolean function(int i, double d, char c)
{
....
}
c:
env->CallBooleanMethod(obj, id_function, 100L, 3.14, L'3');
因为 java中int 类型对应 c中 long 所以 100L
因为 java中char为双字节 所以 L'3'(加L在字符前表示宽字符)
调用实例方法的三种形式:
Call<TYPE>Method(jobject obj, jmethodID id , ...);
这是最常用的一种方式
Call<TYPE>MethodV(jobject obj, jmethodID id, va_list lst);
当调用这个函数的时候有一个指向参数表的va_list变量时使用的
Call<TYPE>MethodA(jobject obj, jmethodID id, jvalue *V);
第三种是当调用这个函数的时候有一个指向jvalue或jvalue数组的指针时用的
jvalue在jni.h中被定义成如下联合体
struts union jvalue{
jboolean z;
jbyte b;
jchar c;
jshort s;
jint i;
jlong j;
jfloat f;
jdouble d;
jobject l;
} jvalue;
(复习 union 就是一个多个变量的结构同时使用一块内存区域,区域的取值大小为该结构中长度最大的变量的值。)
上面的代码可以变成
jvalue *args = new jvalue[3];
jvalue[0].i = 100L;
jvalue[1].d = 3.14;
jvalue[2].c = L'3';
env->CallIntMethod(obj, id_function, jvalue);
***del[] args;
下面看下
第二种:
有如下JAVA代码:
pubblic class Father
{
public void Function()
{
System.out.println("Father::Func");
}
}
public class Child extends Father
{
public void Function()
{
System.out.println((Child::Func");
}
}
思考下 这段java代码调用哪个类的方法
Father p = new Child();
p.Function():
这段代码输出 Child::Func
有如下c++代码
class Father
{
public :
(virtual) void Function()
{
cout << "Father::Func";
}
}
class child : public Father
{
public :
void Function()
{
cout << "Child::Func";
}
}
执行结果:
有virtual :Child::Func
无virtual :Father::Func
在JNI中定义的CallNonvirtual<TYPE>Method就能够实现子类对象调用父类方法的功能。如果想要调用一个对象的父类的方法,而不是子类的这个方法的话,就可以使用CallNonvirtual<TYPE>Method
要使用这个函数的话,首先要取得父类及要调用的父类方法的jmethodID,然后传入到这个函数就能通过子类对象呼叫被覆写的父类的方法了
例
jclass clazz_TestNative = env->GetObjectClass(obj);
jfieldID id_father = env->GetFieldID(clazz_TestNative, "father", "Ltest/jni/Father")
jobject p = env->GetObjectField(obj, id_father);
jclass clazz_Father = env->FindClass("test/jni/Father");
jmethodID id_father_func = env->GetMetherID(clazz_Father,"Function" ,"()V");
env->CallNonvirtualVoidMethod(clazz_father, id_father_func, "()V");
env->CallNonvirtualVoidMethod()