class Callback { static { System.loadLibrary("callback"); } public native void nativeMethod(int depth); // Native Method からコールされるメソッド public void callback(int depth) { String h = ""; if (depth < 5) { for (int i=0; i<depth; i++) h += " "; System.out.println(h+"Java : Depth="+depth); // 再度 Native Method をコールする nativeMethod(depth+1); System.out.println(h+"Java : Depth="+depth); } else { System.out.println(h+"LIMIT"); } } public static void main(String args[]) { Callback c = new Callback(); c.callback(0); } } |
Native Method からコールされるメソッドとして、callback() を用意した。この中でまた Native Method をコールして、深さが 5 になるまで繰り返す。
#include <jni.h> #include "Callback.h" #include <stdio.h> void indent(int level) { int i; for (i=0; i<level; i++) printf(" "); } JNIEXPORT void JNICALL Java_Callback_nativeMethod(JNIEnv *env, jobject obj, jint depth) { jclass cls = (*env)->GetObjectClass(env, obj); jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V"); if (mid == 0) return; indent(depth); printf("C : Depth=%d\n", depth); fflush(stdout); /* Java のメソッドをコール */ (*env)->CallVoidMethod(env, obj, mid, depth); indent(depth); printf("C : Depth=%d\n", depth); fflush(stdout); } |
まず Native Method は、GetObjectClass() により、自分のクラスの Class オブジェクトを取得する。 その Class オブジェクトを使ってメソッドを取得するには、次の GetMethodID() を使う。 この引数にメソッド名 ("callback") と引数・返値 ("(I)V") を渡すと、そのメソッドへの参照が得られる。 もしメソッドが見つからなかった場合、GetMethodID() は 0 を返す。 そして、最後に CallVoidMethod() で Java のメソッドをコールする。
% java Callback Java : Depth=0 C : Depth=1 Java : Depth=1 C : Depth=2 Java : Depth=2 C : Depth=3 Java : Depth=3 C : Depth=4 Java : Depth=4 C : Depth=5 LIMIT C : Depth=5 Java : Depth=4 C : Depth=4 Java : Depth=3 C : Depth=3 Java : Depth=2 C : Depth=2 Java : Depth=1 C : Depth=1 Java : Depth=0