31
31
#ifndef JNI_SINGLETON_H
32
32
#define JNI_SINGLETON_H
33
33
34
+ #include " java_class_wrapper.h"
35
+
34
36
#include " core/config/engine.h"
35
37
#include " core/variant/variant.h"
36
38
37
- #ifdef ANDROID_ENABLED
38
- #include " jni_utils.h"
39
- #endif
40
-
41
39
class JNISingleton : public Object {
42
40
GDCLASS (JNISingleton, Object);
43
41
44
- #ifdef ANDROID_ENABLED
45
42
struct MethodData {
46
- jmethodID method;
47
43
Variant::Type ret_type;
48
44
Vector<Variant::Type> argtypes;
49
45
};
50
46
51
- jobject instance;
52
47
RBMap<StringName, MethodData> method_map;
53
- # endif
48
+ Ref<JavaObject> wrapped_object;
54
49
55
50
public:
56
51
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
+ }
68
64
}
69
65
}
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 ;
82
66
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);
99
69
}
100
70
}
101
71
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.
205
72
return Object::callp (p_method, p_args, p_argcount, r_error);
206
- #endif
207
73
}
208
74
209
- #ifdef ANDROID_ENABLED
210
- jobject get_instance () const {
211
- return instance;
75
+ Ref<JavaObject> get_wrapped_object () const {
76
+ return wrapped_object;
212
77
}
213
78
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) {
219
80
MethodData md;
220
- md.method = p_method;
221
81
md.argtypes = p_args;
222
82
md.ret_type = p_ret_type;
223
83
method_map[p_name] = md;
@@ -232,24 +92,15 @@ class JNISingleton : public Object {
232
92
ADD_SIGNAL (mi);
233
93
}
234
94
235
- # endif
95
+ JNISingleton () {}
236
96
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;
241
99
}
242
100
243
101
~JNISingleton () {
244
- #ifdef ANDROID_ENABLED
245
102
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 ();
253
104
}
254
105
};
255
106
0 commit comments