+/* Thread safe JNIEnv handling */
+
+%inline {
+namespace {
+ class ScopedEnv {
+ public:
+ ScopedEnv(JavaVM *jvm);
+ ~ScopedEnv();
+ JNIEnv* operator-> () { return env; }
+ operator bool () const { return (bool)env; }
+ private:
+ JavaVM *jvm;
+ JNIEnv *env;
+ int env_status;
+ };
+ ScopedEnv::ScopedEnv(JavaVM *jvm) : jvm(jvm), env(NULL) {
+ env_status = jvm->GetEnv((void **)&env, JNI_VERSION_1_2);
+ if (env_status == JNI_EDETACHED) {
+%#if defined(__ANDROID__)
+ jvm->AttachCurrentThread(&env, NULL);
+%#else
+ jvm->AttachCurrentThread((void **)&env, NULL);
+%#endif
+ }
+ }
+ ScopedEnv::~ScopedEnv() {
+ if (env_status == JNI_EDETACHED) {
+ jvm->DetachCurrentThread();
+ }
+ }
+}
+}
+
+/* "Smartpointer" for Java references. */
+
+%inline {
+namespace {
+ class GlobalRefBase
+ {
+ protected:
+ GlobalRefBase (JavaVM *jvm, jobject ref);
+ ~GlobalRefBase ();
+ JavaVM *jvm;
+ jobject jref;
+ };
+ GlobalRefBase::GlobalRefBase (JavaVM *jvm, jobject ref) : jvm(jvm), jref(0) {
+ ScopedEnv env(jvm);
+ if (env && ref)
+ jref = env->NewGlobalRef(ref);
+ }
+ GlobalRefBase::~GlobalRefBase () {
+ ScopedEnv env(jvm);
+ if(env && jref)
+ env->DeleteGlobalRef(jref);
+ }
+ template <class Jtype>
+ class GlobalRef : private GlobalRefBase
+ {
+ public:
+ GlobalRef (JavaVM *jvm, Jtype ref) : GlobalRefBase(jvm, ref) {}
+ GlobalRef (const GlobalRef &ref) : GlobalRefBase(ref.jvm, ref.jref) {}
+ operator Jtype () const { return static_cast<Jtype>(jref); }
+ };
+}
+}
+