三、C++操作java属性と方法


第2話では,C++でjavaプログラムを操作する方法および操作手順について述べたが,JNIが提供する方法をどのように理解するかを実例的に示す.
Javaプロパティ、メソッド、および親メソッドの取得、操作
1、Java属性値の取得/設定
元javaクラスTestNativeに基づいて次のコードを記述します.
package com.fomagic;
public class TestNative {
    
    public native void sayHello(); //C++          
    public int number=10;  //        10, C++     
        
    public static void main(String[] args) {
        System.loadLibrary("NativeCode");//       ,    .dll         
        TestNative test=new TestNative();    //      
        test.sayHello();
        
        System.out.println("C++        :  "+test.number);
    }
 
}

C++には次のコードが追加されています.
JNIEXPORT void JNICALL Java_com_fomagic_TestNative_sayHello (JNIEnv *env, jobject obj)
{
    cout<<"Hello World !"<<endl;
    
    jclass clazz_TestNative=env->GetObjectClass(obj);   //     obj         
    jfieldID id_number=env->GetFieldID(clazz_TestNative,"number","I");  //   ,   ,(sign)    
    jint number =env->GetIntField(obj,id_number); //     ID       
 
    cout<<"   : "<<number <<endl;
 
    env->SetIntField(obj,id_number,100L);  //   ,  ID,    java   
}

       注意:変更された属性値100 Lは、2番目に説明した「JavaタイプのC/C++でのマッピング関係」グラフ(javaでintがC++でlongに対応)を参照してください.
2、Javaクラスを呼び出す方法
インスタンスメソッドを呼び出す3つの形式.
CallMethod(jobject obj ,jmethodID id ,….);
CallMethodV(jobject obj ,jmethodID id ,va_list lst);
CallMethod(jobject obj ,jmethodID id ,jvalue* v) ;
 
最初の比較
2つ目は、この関数を呼び出すとパラメータテーブルを指すva_があります.List変数の場合に使用します(可変パラメータリストであることのみ知ります)
3つ目は、関数を呼び出すときにjvalueまたはjvalue配列を指すポインタがある場合に使用します(すなわち、すべてのパラメータの変数配列ポインタが入力されます).
次に、大きな値を返す例を1つ目に書きます.
 
package com.fomagic;
 
public class TestNative {
    
    public native void sayHello(); //C++      
    public static void main(String[] args) {
        System.loadLibrary("NativeCode");//       ,    .dll         
        TestNative test=new TestNative();    
        test.sayHello();
    }
    double max(double num1,double num2){
        
        return num1>num2 ? num1 : num2;
    }
    
}

 
JNIEXPORT void JNICALL Java_com_fomagic_TestNative_sayHello (JNIEnv *env, jobject obj)
{    
    jclass clazz_TestNative=env->GetObjectClass(obj);  //     
    jmethodID id_max=env->GetMethodID(clazz_TestNative,"max","(DD)D"); //    ID(  )
    jdouble maxValue = env->CallDoubleMethod(obj,id_max,100.5,203.1); //  max      
 
    cout<<"   : "<<maxValue <<endl; }

 
3、Javaクラスの親メソッドを呼び出す
Javaで親が子クラスオブジェクトを作成するには子クラスのオーバーライドメソッドのみを呼び出すことが知られていますが、C++子クラスオブジェクトがデフォルトで呼び出す親メソッドは、親メソッドが仮想関数キーワードvirtualで修飾されている場合に子クラスオーバーライドメソッドを呼び出す
java
C++
Father p=new Child();p.function();          //サブクラスオーバーライドメソッドの呼び出し
Father* p=new Child();p->function();      //デフォルトでは親メソッドが呼び出され、virtual修飾子で修飾するとサブクラスオーバーライドメソッドが呼び出されます.
JNI経由の CallNonvirtualMethodは、親が上書きされたメソッドを呼び出すサブクラスオブジェクトの機能を実現します.
  •       親と呼び出す親のメソッドを取得するjmethodID
  •        jmethodIDを入力 CallNonvirtualMethod

  • コード:新規Fatherクラス、Childクラス
    package com.fomagic;
     
    public class TestNative {
     
        public native void sayHello(); // C++      
        public Father p=new Child();  //  Child      
        
        public static void main(String[] args) {
            System.loadLibrary("NativeCode");//        ,    .dll
            TestNative test = new TestNative();
            test.sayHello();
        }
    }
     
    class Father {
        public void function() {
            System.out.println("Father function");
        }
    }
     
    class Child extends Father {
        public void function() {
            System.out.println("Child function");
        }
    }

    C++コード:
    JNIEXPORT void JNICALL Java_com_fomagic_TestNative_sayHello (JNIEnv *env, jobject obj)
    {
     
        jclass clazz_TestNative=env->GetObjectClass(obj);    
        jfieldID id_p=env->GetFieldID(clazz_TestNative,"p","Lcom/fomagic/Father;");
        jobject p= env->GetObjectField(obj,id_p);
     
        jclass clazz_Father = env->FindClass("com/fomagic/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);
    }

     
    .