关于java:JNI取得Java属性和设置Java属性值

33次阅读

共计 3582 个字符,预计需要花费 9 分钟才能阅读完成。

1. 获得 Java 属性 / 设定 Java 属性值

取得了相应属性的 jfieldID 之后,就能够应用

Set<TYPE>Field
Get<TYPE>Field
SetStatic<TYPE>Field
GetStatic<TYPT>Field

等函数来对 Java 属性进行操作了。

类实例办法

Set/GetBooleanField
Set/GetByteField
Set/GetDoubleField
Set/GetFloatField
Set/GetIntField
Set/GetLongField
Set/GetShortField
Set/GetObjectField

类静态方法

Set/GetStaticBooleanField
Set/GetStaticByteField
Set/GetStaticDoubleField
Set/GetStaticFloatField
Set/GetStaticIntField
Set/GetStaticLongField
Set/GetStaticShortField
Set/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);

正文完
 0