5
5
6
6
#include < string>
7
7
8
+ #include " app/meta/move.h"
9
+ #include " firestore/src/jni/call_traits.h"
10
+ #include " firestore/src/jni/class.h"
8
11
#include " firestore/src/jni/object.h"
9
12
#include " firestore/src/jni/ownership.h"
10
13
#include " firestore/src/jni/string.h"
@@ -14,6 +17,9 @@ namespace firebase {
14
17
namespace firestore {
15
18
namespace jni {
16
19
20
+ // Since we're targeting STLPort, `std::invoke` is not available.
21
+ #define INVOKE (env, method, ...) ((env)->*(method))(__VA_ARGS__);
22
+
17
23
/* *
18
24
* A wrapper around a JNIEnv pointer that makes dealing with JNI simpler in C++,
19
25
* by:
@@ -42,6 +48,119 @@ class Env {
42
48
/* * Returns the underlying JNIEnv pointer. */
43
49
JNIEnv* get () const { return env_; }
44
50
51
+ // MARK: Class Operations
52
+
53
+ /* *
54
+ * Finds the java class associated with the given name which should be
55
+ * formatted like "java/lang/Object".
56
+ */
57
+ Local<Class> FindClass (const char * name);
58
+
59
+ // MARK: Object Operations
60
+
61
+ /* *
62
+ * Creates a new Java object of the given class, returning the result in a
63
+ * reference wrapper of type T.
64
+ *
65
+ * @tparam T The C++ type to which the method should be coerced.
66
+ * @tparam Args The C++ types of the arguments to the method.
67
+ * @param clazz The Java class of the resulting object.
68
+ * @param method The constructor method to invoke.
69
+ * @param args The C++ arguments of the constructor. These will be converted
70
+ * to their JNI equivalent value with a call to ToJni before invocation.
71
+ * @return a local reference to the newly-created object.
72
+ */
73
+ template <typename T = Object, typename ... Args>
74
+ Local<T> New (const Class& clazz, jmethodID method, Args&&... args) {
75
+ if (!ok ()) return {};
76
+
77
+ jobject result =
78
+ env_->NewObject (clazz.get (), method, ToJni (Forward<Args>(args))...);
79
+ RecordException ();
80
+ return MakeResult<T>(result);
81
+ }
82
+
83
+ // MARK: Calling Instance Methods
84
+
85
+ /* *
86
+ * Finds the method on the given class that's associated with the method name
87
+ * and signature.
88
+ */
89
+ jmethodID GetMethodId (const Class& clazz, const char * name, const char * sig);
90
+
91
+ /* *
92
+ * Invokes the JNI instance method using the `Call*Method` appropriate to the
93
+ * return type T.
94
+ *
95
+ * @tparam T The C++ return type to which the method should be coerced.
96
+ * @param object The object to use as `this` for the invocation.
97
+ * @param method The method to invoke.
98
+ * @param args The C++ arguments of the method. These will be converted to
99
+ * their JNI equivalent value with a call to ToJni before invocation.
100
+ * @return The primitive result if T is a primitive, nothing if T is `void`,
101
+ * or a local reference to the returned object.
102
+ */
103
+ template <typename T, typename ... Args>
104
+ ResultType<T> Call (const Object& object, jmethodID method, Args&&... args) {
105
+ auto env_method = CallTraits<JniType<T>>::kCall ;
106
+ return CallHelper<T>(env_method, object.get (), method,
107
+ ToJni (Forward<Args>(args))...);
108
+ }
109
+
110
+ // MARK: Accessing Static Fields
111
+
112
+ jfieldID GetStaticFieldId (const Class& clazz, const char * name,
113
+ const char * sig);
114
+
115
+ /* *
116
+ * Returns the value of the given field using the GetStatic*Field method
117
+ * appropriate to the field type T.
118
+ *
119
+ * @tparam T The C++ type to which the field value should be coerced.
120
+ * @param clazz The class to use as the container for the field.
121
+ * @param field The field to get.
122
+ * @return a local reference to the field value.
123
+ */
124
+ template <typename T = Object>
125
+ ResultType<T> GetStaticField (const Class& clazz, jfieldID field) {
126
+ if (!ok ()) return {};
127
+
128
+ auto env_method = CallTraits<JniType<T>>::kGetStaticField ;
129
+ auto result = INVOKE (env_, env_method, clazz.get (), field);
130
+ RecordException ();
131
+ return MakeResult<T>(result);
132
+ }
133
+
134
+ // MARK: Calling Static Methods
135
+
136
+ /* *
137
+ * Finds the method on the given class that's associated with the method name
138
+ * and signature.
139
+ */
140
+ jmethodID GetStaticMethodId (const Class& clazz, const char * name,
141
+ const char * sig);
142
+
143
+ /* *
144
+ * Invokes the JNI static method using the CallStatic*Method appropriate to
145
+ * the return type T.
146
+ *
147
+ * @tparam T The C++ return type to which the method should be coerced.
148
+ * @tparam Args The C++ types of the arguments to the method.
149
+ * @param clazz The class against which to invoke the static method.
150
+ * @param method The method to invoke.
151
+ * @param args The C++ arguments of the method. These will be converted to
152
+ * their JNI equivalent value with a call to ToJni before invocation.
153
+ * @return The primitive result if T is a primitive, nothing if T is `void`,
154
+ * or a local reference to the returned object.
155
+ */
156
+ template <typename T, typename ... Args>
157
+ ResultType<T> CallStatic (const Class& clazz, jmethodID method,
158
+ Args&&... args) {
159
+ auto env_method = CallTraits<JniType<T>>::kCallStatic ;
160
+ return CallHelper<T>(env_method, clazz.get (), method,
161
+ ToJni (Forward<Args>(args))...);
162
+ }
163
+
45
164
// MARK: String Operations
46
165
47
166
/* *
@@ -74,12 +193,66 @@ class Env {
74
193
}
75
194
76
195
private:
196
+ /* *
197
+ * Invokes the JNI instance method using the given method reference on JNIEnv.
198
+ *
199
+ * @tparam T The non-void C++ return type to which the method's result should
200
+ * be coerced.
201
+ * @param env_method A method reference from JNIEnv, appropriate for the
202
+ * return type T, and the kind of method being invoked (instance or
203
+ * static). Use `CallTraits<JniType<T>>::kCall` or `kCallStatic` to find
204
+ * the right method.
205
+ * @param args The method and JNI arguments of the JNI method, including the
206
+ * class or object, jmethodID, and any arguments to pass.
207
+ * @return The primitive result if T is a primitive or a local reference to
208
+ * the returned object.
209
+ */
210
+ template <typename T, typename M, typename ... Args>
211
+ typename enable_if<!is_same<T, void >::value, ResultType<T>>::type CallHelper (
212
+ M&& env_method, Args&&... args) {
213
+ if (!ok ()) return {};
214
+
215
+ auto result = INVOKE (env_, env_method, Forward<Args>(args)...);
216
+ RecordException ();
217
+ return MakeResult<T>(result);
218
+ }
219
+
220
+ /* *
221
+ * Invokes a JNI call method if the return type is `void`.
222
+ *
223
+ * If `T` is anything but `void`, the overload is disabled.
224
+ */
225
+ template <typename T, typename M, typename ... Args>
226
+ typename enable_if<is_same<T, void >::value, void >::type CallHelper (
227
+ M&& env_method, Args&&... args) {
228
+ if (!ok ()) return ;
229
+
230
+ INVOKE (env_, env_method, Forward<Args>(args)...);
231
+ RecordException ();
232
+ }
233
+
77
234
void RecordException ();
78
235
236
+ template <typename T>
237
+ EnableForPrimitive<T, T> MakeResult (JniType<T> value) {
238
+ return static_cast <T>(value);
239
+ }
240
+
241
+ template <typename T>
242
+ EnableForReference<T, Local<T>> MakeResult (jobject object) {
243
+ // JNI object method results are always jobject, even when the actual type
244
+ // is jstring or jclass. Cast to the correct type here so that Local<T>
245
+ // doesn't have to account for this.
246
+ auto typed_object = static_cast <JniType<T>>(object);
247
+ return Local<T>(env_, typed_object);
248
+ }
249
+
79
250
JNIEnv* env_ = nullptr ;
80
251
jthrowable last_exception_ = nullptr ;
81
252
};
82
253
254
+ #undef INVOKE
255
+
83
256
} // namespace jni
84
257
} // namespace firestore
85
258
} // namespace firebase
0 commit comments