Android JNIで見掛けたインスタンス管理テクニック
Shared Libraryを作成するとき、
インスタンスの管理はなかなか悩ましい問題ですが、
Androidのmediaパッケージで、
JNIを利用したちょっと変わったインスタンス管理をやっていたので紹介&覚書。
/* envはJNIEnv*, thizはjobjectで、JNI呼び出しクラスのインスタンス */
/* NativeClassはAndroidミドル側の適当なクラス */
jclazz clazz = env->FindClass("hoge/foo/JavaClass");
jfieldID context = env->GetFieldID(clazz, "mNativeContext", "I");
NativeClass* pNative = new NativeClass;
env->SetIntField(thiz, context, (int)pNative);
これは、hoge.foo.JavaClassクラスのメンバ変数mNativeContextに、
(例えばprivate int mNativeContext)
NativeClassのインスタンスポインタを渡している処理を行っています。
こうすることで、Java側のJavaClassインスタンスと、
C++側のNativeClassインスタンスとを、1対1対応させることができます。
なお、JNI呼び出しクラスのインスタンスがJavaClassクラスのインスタンスでなければ、
参照エラーが起きると思います。
NativeClassインスタンスを取り出すときは、こんな感じです。
NativeClass* p = (NativeClass*)env->GetIntField(thiz, context);
JNIだと、こんな変わったインスタンス管理もできるんですねえ。
Javaクラスのコードとネイティブコードの結合性が高くなってしまいますが、
AdapterのJavaクラスを含めて、ライブラリの提供をするだろうと思いますので、
それほどデメリットにはならないかと思います。