/*********************************************************************** * director.swg * * This file contains support for director classes that proxy * method calls from C++ to Java extensions. * * Author : Scott Michel (scottm@aero.org) * * This file was adapted from the python director.swg, written by * Mark Rose (mrose@stm.lbl.gov) ************************************************************************/ #ifdef __cplusplus #if defined(DEBUG_DIRECTOR_OWNED) #include #endif namespace Swig { /* Java object wrapper */ class JObjectWrapper { public: JObjectWrapper() : jthis_(NULL), weak_global_(true) { } ~JObjectWrapper() { jthis_ = NULL; weak_global_ = true; } bool set(JNIEnv *jenv, jobject jobj, bool mem_own, bool weak_global) { if (jthis_ == NULL) { weak_global_ = weak_global; if (jobj) jthis_ = ((weak_global_ || !mem_own) ? jenv->NewWeakGlobalRef(jobj) : jenv->NewGlobalRef(jobj)); #if defined(DEBUG_DIRECTOR_OWNED) std::cout << "JObjectWrapper::set(" << jobj << ", " << (weak_global ? "weak_global" : "global_ref") << ") -> " << jthis_ << std::endl; #endif return true; } else { #if defined(DEBUG_DIRECTOR_OWNED) std::cout << "JObjectWrapper::set(" << jobj << ", " << (weak_global ? "weak_global" : "global_ref") << ") -> already set" << std::endl; #endif return false; } } jobject get(JNIEnv *jenv) const { #if defined(DEBUG_DIRECTOR_OWNED) std::cout << "JObjectWrapper::get("; if (jthis_) std::cout << jthis_; else std::cout << "null"; std::cout << ") -> return new local ref" << std::endl; #endif return (jthis_ ? jenv->NewLocalRef(jthis_) : jthis_); } void release(JNIEnv *jenv) { #if defined(DEBUG_DIRECTOR_OWNED) std::cout << "JObjectWrapper::release(" << jthis_ << "): " << (weak_global_ ? "local ref" : "global ref") << std::endl; #endif if (weak_global_) jenv->DeleteWeakGlobalRef(jthis_); else jenv->DeleteGlobalRef(jthis_); jthis_ = NULL; weak_global_ = true; } jobject peek() { return jthis_; } private: /* pointer to Java object */ jobject jthis_; /* Local or global reference flag */ bool weak_global_; }; /* director base class */ class Director { private: /* pointer to Java virtual machine */ JavaVM *swig_jvm_; protected: /* Java object wrapper */ JObjectWrapper swig_self_; /* Acquire Java VM environment from Java VM */ JNIEnv *swig_acquire_jenv() const { JNIEnv *env = NULL; swig_jvm_->AttachCurrentThread((void **) &env, NULL); return env; } /* Disconnect director from Java object */ void swig_disconnect_director_self(const char *disconn_method) { JNIEnv *jenv = swig_acquire_jenv(); jobject jobj = swig_self_.get(jenv); #if defined(DEBUG_DIRECTOR_OWNED) std::cout << "Swig::Director::disconnect_director_self(" << jobj << ")" << std::endl; #endif if (jobj) { jmethodID disconn_meth = jenv->GetMethodID(jenv->GetObjectClass(jobj), disconn_method, "()V"); if (disconn_meth) { jenv->CallVoidMethod(jobj, disconn_meth); } else { jenv->ExceptionClear(); } } } public: Director(JNIEnv *jenv) : swig_jvm_((JavaVM *) NULL), swig_self_() { /* Acquire the Java VM pointer */ jenv->GetJavaVM(&swig_jvm_); } virtual ~Director() { swig_self_.release(swig_acquire_jenv()); } bool swig_set_self(JNIEnv *jenv, jobject jself, bool mem_own, bool weak_global) { return swig_self_.set(jenv, jself, mem_own, weak_global); } jobject swig_get_self(JNIEnv *jenv) const { return swig_self_.get(jenv); } }; } #endif /* __cplusplus */