Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /*********************************************************************** |
2 | * director.swg | |
3 | * | |
4 | * This file contains support for director classes that proxy | |
5 | * method calls from C++ to Java extensions. | |
6 | * | |
7 | * Author : Scott Michel (scottm@aero.org) | |
8 | * | |
9 | * This file was adapted from the python director.swg, written by | |
10 | * Mark Rose (mrose@stm.lbl.gov) | |
11 | ************************************************************************/ | |
12 | ||
13 | #ifdef __cplusplus | |
14 | ||
15 | #if defined(DEBUG_DIRECTOR_OWNED) | |
16 | #include <iostream> | |
17 | #endif | |
18 | ||
19 | namespace Swig { | |
20 | /* Java object wrapper */ | |
21 | class JObjectWrapper { | |
22 | public: | |
23 | JObjectWrapper() : jthis_(NULL), weak_global_(true) { | |
24 | } | |
25 | ||
26 | ~JObjectWrapper() { | |
27 | jthis_ = NULL; | |
28 | weak_global_ = true; | |
29 | } | |
30 | ||
31 | bool set(JNIEnv *jenv, jobject jobj, bool mem_own, bool weak_global) { | |
32 | if (jthis_ == NULL) { | |
33 | weak_global_ = weak_global; | |
34 | if (jobj) | |
35 | jthis_ = ((weak_global_ || !mem_own) ? jenv->NewWeakGlobalRef(jobj) : jenv->NewGlobalRef(jobj)); | |
36 | #if defined(DEBUG_DIRECTOR_OWNED) | |
37 | std::cout << "JObjectWrapper::set(" << jobj << ", " << (weak_global ? "weak_global" : "global_ref") << ") -> " << jthis_ << std::endl; | |
38 | #endif | |
39 | return true; | |
40 | } else { | |
41 | #if defined(DEBUG_DIRECTOR_OWNED) | |
42 | std::cout << "JObjectWrapper::set(" << jobj << ", " << (weak_global ? "weak_global" : "global_ref") << ") -> already set" << std::endl; | |
43 | #endif | |
44 | return false; | |
45 | } | |
46 | } | |
47 | ||
48 | jobject get(JNIEnv *jenv) const { | |
49 | #if defined(DEBUG_DIRECTOR_OWNED) | |
50 | std::cout << "JObjectWrapper::get("; | |
51 | if (jthis_) | |
52 | std::cout << jthis_; | |
53 | else | |
54 | std::cout << "null"; | |
55 | std::cout << ") -> return new local ref" << std::endl; | |
56 | #endif | |
57 | return (jthis_ ? jenv->NewLocalRef(jthis_) : jthis_); | |
58 | } | |
59 | ||
60 | void release(JNIEnv *jenv) { | |
61 | #if defined(DEBUG_DIRECTOR_OWNED) | |
62 | std::cout << "JObjectWrapper::release(" << jthis_ << "): " << (weak_global_ ? "weak global ref" : "global ref") << std::endl; | |
63 | #endif | |
64 | if (jthis_ != NULL) { | |
65 | if (weak_global_) { | |
66 | if (jenv->IsSameObject(jthis_, NULL) == JNI_FALSE) | |
67 | jenv->DeleteWeakGlobalRef((jweak)jthis_); | |
68 | } else | |
69 | jenv->DeleteGlobalRef(jthis_); | |
70 | } | |
71 | ||
72 | jthis_ = NULL; | |
73 | weak_global_ = true; | |
74 | } | |
75 | ||
76 | jobject peek() { | |
77 | return jthis_; | |
78 | } | |
79 | ||
80 | /* Java proxy releases ownership of C++ object, C++ object is now | |
81 | responsible for destruction (creates NewGlobalRef to pin Java | |
82 | proxy) */ | |
83 | void java_change_ownership(JNIEnv *jenv, jobject jself, bool take_or_release) { | |
84 | if (take_or_release) { /* Java takes ownership of C++ object's lifetime. */ | |
85 | if (!weak_global_) { | |
86 | jenv->DeleteGlobalRef(jthis_); | |
87 | jthis_ = jenv->NewWeakGlobalRef(jself); | |
88 | weak_global_ = true; | |
89 | } | |
90 | } else { /* Java releases ownership of C++ object's lifetime */ | |
91 | if (weak_global_) { | |
92 | jenv->DeleteWeakGlobalRef((jweak)jthis_); | |
93 | jthis_ = jenv->NewGlobalRef(jself); | |
94 | weak_global_ = false; | |
95 | } | |
96 | } | |
97 | } | |
98 | ||
99 | private: | |
100 | /* pointer to Java object */ | |
101 | jobject jthis_; | |
102 | /* Local or global reference flag */ | |
103 | bool weak_global_; | |
104 | }; | |
105 | ||
106 | /* director base class */ | |
107 | class Director { | |
108 | private: | |
109 | /* pointer to Java virtual machine */ | |
110 | JavaVM *swig_jvm_; | |
111 | ||
112 | protected: | |
113 | /* Java object wrapper */ | |
114 | JObjectWrapper swig_self_; | |
115 | ||
116 | /* Acquire Java VM environment from Java VM */ | |
117 | JNIEnv *swig_acquire_jenv() const { | |
118 | JNIEnv *env = NULL; | |
119 | swig_jvm_->AttachCurrentThread((void **) &env, NULL); | |
120 | return env; | |
121 | } | |
122 | ||
123 | /* Disconnect director from Java object */ | |
124 | void swig_disconnect_director_self(const char *disconn_method) { | |
125 | JNIEnv *jenv = swig_acquire_jenv(); | |
126 | jobject jobj = swig_self_.peek(); | |
127 | #if defined(DEBUG_DIRECTOR_OWNED) | |
128 | std::cout << "Swig::Director::disconnect_director_self(" << jobj << ")" << std::endl; | |
129 | #endif | |
130 | if (jobj && jenv->IsSameObject(jobj, NULL) == JNI_FALSE) { | |
131 | jmethodID disconn_meth = jenv->GetMethodID(jenv->GetObjectClass(jobj), disconn_method, "()V"); | |
132 | if (disconn_meth) { | |
133 | #if defined(DEBUG_DIRECTOR_OWNED) | |
134 | std::cout << "Swig::Director::disconnect_director_self upcall to " << disconn_method << std::endl; | |
135 | #endif | |
136 | jenv->CallVoidMethod(jobj, disconn_meth); | |
137 | } | |
138 | } | |
139 | } | |
140 | ||
141 | public: | |
142 | Director(JNIEnv *jenv) : swig_jvm_((JavaVM *) NULL), swig_self_() { | |
143 | /* Acquire the Java VM pointer */ | |
144 | jenv->GetJavaVM(&swig_jvm_); | |
145 | } | |
146 | ||
147 | virtual ~Director() { | |
148 | swig_self_.release(swig_acquire_jenv()); | |
149 | } | |
150 | ||
151 | bool swig_set_self(JNIEnv *jenv, jobject jself, bool mem_own, bool weak_global) { | |
152 | return swig_self_.set(jenv, jself, mem_own, weak_global); | |
153 | } | |
154 | ||
155 | jobject swig_get_self(JNIEnv *jenv) const { | |
156 | return swig_self_.get(jenv); | |
157 | } | |
158 | ||
159 | // Change C++ object's ownership, relative to Java | |
160 | void swig_java_change_ownership(JNIEnv *jenv, jobject jself, bool take_or_release) { | |
161 | swig_self_.java_change_ownership(jenv, jself, take_or_release); | |
162 | } | |
163 | }; | |
164 | } | |
165 | ||
166 | #endif /* __cplusplus */ | |
167 | ||
168 |