3131#ifndef JNI_SINGLETON_H
3232#define JNI_SINGLETON_H
3333
34+ #include " java_class_wrapper.h"
35+
3436#include " core/config/engine.h"
3537#include " core/variant/variant.h"
3638
37- #ifdef ANDROID_ENABLED
38- #include " jni_utils.h"
39- #endif
40-
4139class JNISingleton : public Object {
4240 GDCLASS (JNISingleton, Object);
4341
44- #ifdef ANDROID_ENABLED
4542 struct MethodData {
46- jmethodID method;
4743 Variant::Type ret_type;
4844 Vector<Variant::Type> argtypes;
4945 };
5046
51- jobject instance;
5247 RBMap<StringName, MethodData> method_map;
53- # endif
48+ Ref<JavaObject> wrapped_object;
5449
5550public:
5651 virtual Variant callp (const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override {
57- #ifdef ANDROID_ENABLED
58- RBMap<StringName, MethodData>::Element *E = method_map.find (p_method);
59-
60- // Check the method we're looking for is in the JNISingleton map and that
61- // the arguments match.
62- bool call_error = !E || E->get ().argtypes .size () != p_argcount;
63- if (!call_error) {
64- for (int i = 0 ; i < p_argcount; i++) {
65- if (!Variant::can_convert (p_args[i]->get_type (), E->get ().argtypes [i])) {
66- call_error = true ;
67- break ;
52+ if (wrapped_object.is_valid ()) {
53+ RBMap<StringName, MethodData>::Element *E = method_map.find (p_method);
54+
55+ // Check the method we're looking for is in the JNISingleton map and that
56+ // the arguments match.
57+ bool call_error = !E || E->get ().argtypes .size () != p_argcount;
58+ if (!call_error) {
59+ for (int i = 0 ; i < p_argcount; i++) {
60+ if (!Variant::can_convert (p_args[i]->get_type (), E->get ().argtypes [i])) {
61+ call_error = true ;
62+ break ;
63+ }
6864 }
6965 }
70- }
71-
72- if (call_error) {
73- // The method is not in this map, defaulting to the regular instance calls.
74- return Object::callp (p_method, p_args, p_argcount, r_error);
75- }
76-
77- ERR_FAIL_NULL_V (instance, Variant ());
78-
79- r_error.error = Callable::CallError::CALL_OK;
80-
81- jvalue *v = nullptr ;
8266
83- if (p_argcount) {
84- v = (jvalue *)alloca (sizeof (jvalue) * p_argcount);
85- }
86-
87- JNIEnv *env = get_jni_env ();
88-
89- int res = env->PushLocalFrame (16 );
90-
91- ERR_FAIL_COND_V (res != 0 , Variant ());
92-
93- List<jobject> to_erase;
94- for (int i = 0 ; i < p_argcount; i++) {
95- jvalret vr = _variant_to_jvalue (env, E->get ().argtypes [i], p_args[i]);
96- v[i] = vr.val ;
97- if (vr.obj ) {
98- to_erase.push_back (vr.obj );
67+ if (!call_error) {
68+ return wrapped_object->callp (p_method, p_args, p_argcount, r_error);
9969 }
10070 }
10171
102- Variant ret;
103-
104- switch (E->get ().ret_type ) {
105- case Variant::NIL: {
106- env->CallVoidMethodA (instance, E->get ().method , v);
107- } break ;
108- case Variant::BOOL: {
109- ret = env->CallBooleanMethodA (instance, E->get ().method , v) == JNI_TRUE;
110- } break ;
111- case Variant::INT: {
112- ret = env->CallIntMethodA (instance, E->get ().method , v);
113- } break ;
114- case Variant::FLOAT: {
115- ret = env->CallFloatMethodA (instance, E->get ().method , v);
116- } break ;
117- case Variant::STRING: {
118- jobject o = env->CallObjectMethodA (instance, E->get ().method , v);
119- ret = jstring_to_string ((jstring)o, env);
120- env->DeleteLocalRef (o);
121- } break ;
122- case Variant::PACKED_STRING_ARRAY: {
123- jobjectArray arr = (jobjectArray)env->CallObjectMethodA (instance, E->get ().method , v);
124-
125- ret = _jobject_to_variant (env, arr);
126-
127- env->DeleteLocalRef (arr);
128- } break ;
129- case Variant::PACKED_INT32_ARRAY: {
130- jintArray arr = (jintArray)env->CallObjectMethodA (instance, E->get ().method , v);
131-
132- int fCount = env->GetArrayLength (arr);
133- Vector<int > sarr;
134- sarr.resize (fCount );
135-
136- int *w = sarr.ptrw ();
137- env->GetIntArrayRegion (arr, 0 , fCount , w);
138- ret = sarr;
139- env->DeleteLocalRef (arr);
140- } break ;
141- case Variant::PACKED_INT64_ARRAY: {
142- jlongArray arr = (jlongArray)env->CallObjectMethodA (instance, E->get ().method , v);
143-
144- int fCount = env->GetArrayLength (arr);
145- Vector<int64_t > sarr;
146- sarr.resize (fCount );
147-
148- int64_t *w = sarr.ptrw ();
149- env->GetLongArrayRegion (arr, 0 , fCount , w);
150- ret = sarr;
151- env->DeleteLocalRef (arr);
152- } break ;
153- case Variant::PACKED_FLOAT32_ARRAY: {
154- jfloatArray arr = (jfloatArray)env->CallObjectMethodA (instance, E->get ().method , v);
155-
156- int fCount = env->GetArrayLength (arr);
157- Vector<float > sarr;
158- sarr.resize (fCount );
159-
160- float *w = sarr.ptrw ();
161- env->GetFloatArrayRegion (arr, 0 , fCount , w);
162- ret = sarr;
163- env->DeleteLocalRef (arr);
164- } break ;
165- case Variant::PACKED_FLOAT64_ARRAY: {
166- jdoubleArray arr = (jdoubleArray)env->CallObjectMethodA (instance, E->get ().method , v);
167-
168- int fCount = env->GetArrayLength (arr);
169- Vector<double > sarr;
170- sarr.resize (fCount );
171-
172- double *w = sarr.ptrw ();
173- env->GetDoubleArrayRegion (arr, 0 , fCount , w);
174- ret = sarr;
175- env->DeleteLocalRef (arr);
176- } break ;
177- case Variant::DICTIONARY: {
178- jobject obj = env->CallObjectMethodA (instance, E->get ().method , v);
179- ret = _jobject_to_variant (env, obj);
180- env->DeleteLocalRef (obj);
181-
182- } break ;
183- case Variant::OBJECT: {
184- jobject obj = env->CallObjectMethodA (instance, E->get ().method , v);
185- ret = _jobject_to_variant (env, obj);
186- env->DeleteLocalRef (obj);
187- } break ;
188- default : {
189- env->PopLocalFrame (nullptr );
190- ERR_FAIL_V (Variant ());
191- } break ;
192- }
193-
194- while (to_erase.size ()) {
195- env->DeleteLocalRef (to_erase.front ()->get ());
196- to_erase.pop_front ();
197- }
198-
199- env->PopLocalFrame (nullptr );
200-
201- return ret;
202- #else // ANDROID_ENABLED
203-
204- // Defaulting to the regular instance calls.
20572 return Object::callp (p_method, p_args, p_argcount, r_error);
206- #endif
20773 }
20874
209- #ifdef ANDROID_ENABLED
210- jobject get_instance () const {
211- return instance;
75+ Ref<JavaObject> get_wrapped_object () const {
76+ return wrapped_object;
21277 }
21378
214- void set_instance (jobject p_instance) {
215- instance = p_instance;
216- }
217-
218- void add_method (const StringName &p_name, jmethodID p_method, const Vector<Variant::Type> &p_args, Variant::Type p_ret_type) {
79+ void add_method (const StringName &p_name, const Vector<Variant::Type> &p_args, Variant::Type p_ret_type) {
21980 MethodData md;
220- md.method = p_method;
22181 md.argtypes = p_args;
22282 md.ret_type = p_ret_type;
22383 method_map[p_name] = md;
@@ -232,24 +92,15 @@ class JNISingleton : public Object {
23292 ADD_SIGNAL (mi);
23393 }
23494
235- # endif
95+ JNISingleton () {}
23696
237- JNISingleton () {
238- #ifdef ANDROID_ENABLED
239- instance = nullptr ;
240- #endif
97+ JNISingleton (const Ref<JavaObject> &p_wrapped_object) {
98+ wrapped_object = p_wrapped_object;
24199 }
242100
243101 ~JNISingleton () {
244- #ifdef ANDROID_ENABLED
245102 method_map.clear ();
246- if (instance) {
247- JNIEnv *env = get_jni_env ();
248- ERR_FAIL_NULL (env);
249-
250- env->DeleteGlobalRef (instance);
251- }
252- #endif
103+ wrapped_object.unref ();
253104 }
254105};
255106
0 commit comments