■
問題はnative側のオブジェクトへの参照をいかにJava側へ渡すかである.類似の議論は, JavaHouse, JavaWorldなどで行われている.Java側で JMOSSite.AccessDrawer()が JMOSDrawer(CMOSSite) を呼ぶようにしたところ,CMOSSite->AccessDrawer()までは動作(この時点でMAPPERのSYSTEM を見るとCabinetTOCとなっている)するようになったが,getHashCode()でエラーとなりRegistryへの登録ができない.getHashCode()に渡そうとしているポインタがJMOSDrawerではなくCMOSDrawerだからでは?
Registryに登録されるのは,つまりJava側のオブジェクト(jobject)とnative側のオブジェクトのマッピングである.必ずしもJava側とnative側のコンストラクタが同期する必要はない.そこで以下のようにすることで,JMOSSite.AccessDrawer()の件をついに解決.
public class JMOSSite { public JMOSDrawer AccessDrawer(String drawerName) { JMOSDrawer jd = new JMOSDrawer(); jd = AccessDrawer(jd, drawerName); return(jd); }; private native JMOSDrawer AccessDrawer(JMOSDrawer jd, String drawerName); }
JNIEXPORT jobject JNICALL Java_JMOSSite_AccessDrawer (JNIEnv *env, jobject jmosSite, jobject jmosDrawer, jstring drw) { CMOSSite *c; CMOSDrawer *d; jboolean isCopy1; char *drawerName;
jint hashCode = getHashCode(env, jmosSite); Registry::lookup((void*)hashCode, (void*&) c);
drawerName = (char *) env->GetStringUTFChars(drw, &isCopy1); d = c->AccessDrawer((const char *)drawerName); hashCode = getHashCode(env, jmosDrawer); Registry::add((void*) hashCode, (void*&) d); if (isCopy1 == JNI_TRUE) env->ReleaseStringUTFChars(drw,drawerName);
return(jmosDrawer); }
JNIEXPORT void JNICALL Java_JMOSDrawer__1jni_1initialize (JNIEnv *env, jobject jmosDrawer) { jint hashCode = getHashCode(env, jmosDrawer); // CMOSDrawer *cmosDrawer = new CMOSDrawer((const char *)DrawerName, (CMO SSession *)jmosSession); // Registry::add((void*) hashCode, (void*&) cmosDrawer); }
つまりJMOSSiteには,
public JMOSDrawer AccessDrawer(String drawerName) private native JMOSDrawer AccessDrawer(JMOSDrawer jd, String drawerName)
2種類のAccessDrawer()メソッドを用意.AccessDrawer(String)はJMOSDrawerを初期化し,その参照をAccessDrawer(JMOSDrawer,String)に渡す.JMOSDrawerのコンスラクタは何もしない(インスタンスを初期化するだけ).AccessDrawer(JMOSDrawer,String)はnative側のAccessDrawerを呼び出し,この中でRegistryへの登録を行う.