JNIプログラミング(二)--C++とJavaを相互に呼び出す(2)

3380 ワード

3.getRamdomOrder()
 
このメソッドはbackendからランダムなOrderオブジェクト(ここで「Random」のスペルが間違っていることを申し訳ありません)を取得し、javaの対応する通知メソッドを呼び出してforegroundに通知します.getRamdomOrderメソッドにはパラメータはありませんが、対応するC++メソッドには2つのパラメータがあり、理解できない人もいるに違いありません.実は注意深い友达はきっと発见して、JNIの中ですべてJavaの方法に対応するC++の方法はすべてJavaの方法より2つのパラメータが多くて、第1のパラメータは私达のとても熟知しているJNIEnv*の指针で、第2のパラメータは时にはjobjectで时にはjclassです.この2番目のパラメータに対しては,ここで余計なことを言う必要がある.
 
実は2番目のパラメータはnativeローカルメソッドを含むオブジェクトまたはクラスオブジェクトを伝達し、非静的メソッドはあるオブジェクトに属し、静的メソッドはクラスオブジェクトに属するので、静的メソッドはすべてのオブジェクトで共有することができることを知っています.このオブジェクト/クラスオブジェクトがあれば,nativeメソッドを含むオブジェクトのいくつかの関数を容易に操作できる.(この言葉は少し早口で、読めなかったアドバイスを2回も読みました).
 
くだらない話は本題に戻りますが、getRamdomOrderは静的ではないので、C++に対応するパラメータにjobjectオブジェクトが渡されます.
 
jclass business_class = env->GetObjectClass(obj);

 
GetObjectClassメソッドはJavaのObject.classに似たオブジェクトのクラスオブジェクトを得ることができます.慣れない友人はJava反射メカニズムをもう一度見に行くことをお勧めします.次のいくつかのC++コードは、前の方法1と方法2で説明されているはずです.早くbackend側からforegroundに「メッセージ」が送られ、newの新しいOrderクラスが出てきます.次の3つの言葉はもうくだらないことを言う必要がある.
 
	jfieldID amount_field = env->GetFieldID(order_class, "amount", "I");
	jint amount = env->GetIntField(order, amount_field);
	cout << "amount: " << amount << endl;

 
以前はOrderというJavabeanのamountの属性に初期値30を設定していましたが、実はここでC++でJavaオブジェクトの属性を持つ方法を実証するために、持つ方法と私たちが前に言ったJavaメソッドを呼び出すプログラムの差は少なく、jfieldIDを先に取得し、その後GetFieldメソッドを呼び出してあるオブジェクトの属性の数値を取得するために、最後にcoutは彼を印刷した.テストコードを作成して最終的な効果を見てみましょう.
 
		Business b = new Business();				 
		Order o2 = b.getRamdomOrder();
		System.out.println(o2.getName());

 
上記のテストコードを実行すると、コンソールから
 
Got a notification. amount: 30 Fruit
 
私たちが望んでいる結果と同じように、テストに成功しました.
 
4.analyzeOrder(Order order)
 
これは静的メソッドで、foregroundはこのメソッドを通じてOrderのオブジェクトをbackendに渡し、CPP側で「analyze」を行います.ここでは、渡されたOrderオブジェクトのnameプロパティを取り出し、コンソールに印刷します.この方法は静的static法であるため,対応するC++法の2番目のパラメータもjclassオブジェクト,すなわちBusiness.classというクラスオブジェクトとなる.3番目のパラメータはjobjectオブジェクトであり,明らかに我々が渡したorderオブジェクトである.
 
最初の5文のコードは理解しにくいはずですが、getNameという方法を呼び出して印刷します.JNIのAPIではCallStringMethodという方法は提供されていないので、CallObjectMethodという方法でnameという文字列(Stringは明らかにObject)を取得し、jstringに移行します.つまり、次のコードです.
 
	jstring name_str = static_cast(env->CallObjectMethod(obj, getName_method));
 
nameという文字列を取得した後coutが印刷され、Businessというクラスオブジェクトの静的メソッドnotificationByStaticがforegroundに通知されるように呼び出されます.呼び出しの流れおよびメソッドは静的でないものと同じであるが、JNIで静的メソッドを呼び出すAPIが伝達するパラメータの1つがjobjectではなくjclassであることに注意する(これも理解に難くない.静的メソッドはclassクラスオブジェクトに属するため)
 
テストコードを作成してテストする方法です
 
		Business b = new Business();		
		Order o = b.getOrder("Watermelom", 100);
		Business.analyzeOrder(o);
 
コンソールからの印刷
 
Name in Java_com_chnic_service_Business_analyzeOrder: Watermelom Got a notification in a static method.
 
1文目はC++のcoutで印刷され、2文目はJavaの静的メソッドで印刷され、私たちが望んでいる結果と一致しています.
 
 
ふ~やっと4つの方法を紹介したので、最後にまとめましょう.
 
  • JNIで提供されるAPIは、この4つの方法で使用されるAPIよりもはるかに大きい.上で紹介したのは比較的よく使われているので、本人もすべてのAPIを羅列することはできません.
  • JNIプログラミングを理解することは、Javaにおける反射メカニズムをより深く理解するのに有利であり、逆も同様である.

  •  
    したがって、JNIプログラミングに興味があるか、より深いニーズがある場合は、sunの関連ドキュメントを参照してください.ここではsunが提供するJNIのAPIマニュアルをアップロードし、上記の例で使用したプレゼンテーションコードも参考にします.