java学习之JNI 学习三 取得JAVA属性/设定JAVA属性值

  •      取得JAVA属性/设定JAVA属性值

      在取得了相应属性的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

 

 

  • JAVA方法的调用

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()

 

 

 

 

 

你可能感兴趣的:(java,function,struts,list,jni,Class)