lime
Lime is a C++ library implementing Open Whisper System Signal protocol
Loading...
Searching...
No Matches
native_method.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <jni/types.hpp>
4#include <jni/errors.hpp>
5#include <jni/functions.hpp>
6#include <jni/tagging.hpp>
7#include <jni/class.hpp>
8#include <jni/object.hpp>
9
10#include <exception>
11#include <type_traits>
12
13namespace jni
14 {
15 template < class M, class Enable = void >
17
18 template < class R, class... Args >
19 struct NativeMethodTraits< R (Args...) >
20 {
21 using Type = R (Args...);
22 using ResultType = R;
23 };
24
25 template < class R, class... Args >
26 struct NativeMethodTraits< R (*)(Args...) >
27 : NativeMethodTraits< R (Args...) > {};
28
29 template < class T, class R, class... Args >
30 struct NativeMethodTraits< R (T::*)(Args...) const >
31 : NativeMethodTraits< R (Args...) > {};
32
33 template < class T, class R, class... Args >
34 struct NativeMethodTraits< R (T::*)(Args...) >
35 : NativeMethodTraits< R (Args...) > {};
36
37 template < class M >
38 struct NativeMethodTraits< M, std::enable_if_t< std::is_class<M>::value > >
39 : NativeMethodTraits< decltype(&M::operator()) > {};
40
41
43
44 template < class M >
45 auto MakeNativeMethod(const char* name, const char* sig, const M& m,
46 std::enable_if_t< std::is_class<M>::value >* = nullptr)
47 {
49 using ResultType = typename NativeMethodTraits<M>::ResultType;
50
51 static FunctionType* method = m;
52
53 auto wrapper = [] (JNIEnv* env, auto... args)
54 {
55 try
56 {
57 return method(env, args...);
58 }
59 catch (...)
60 {
61 ThrowJavaError(*env, std::current_exception());
62 return ResultType();
63 }
64 };
65
67 }
68
69
71
72 template < class M, M method >
73 auto MakeNativeMethod(const char* name, const char* sig)
74 {
76 using ResultType = typename NativeMethodTraits<M>::ResultType;
77
78 auto wrapper = [] (JNIEnv* env, auto... args)
79 {
80 try
81 {
82 return method(env, args...);
83 }
84 catch (...)
85 {
86 ThrowJavaError(*env, std::current_exception());
87 return ResultType();
88 }
89 };
90
92 }
93
94
96
97 template < class T, T*... >
99
100 template < class T, class R, class Subject, class... Args >
101 struct NativeMethodMaker< R (T::*)(JNIEnv&, Subject, Args...) const >
102 {
103 template < class M >
104 auto operator()(const char* name, const M& m)
105 {
106 static M method(m);
107
109 {
110 return ReleaseUnique(method(*env, AsLvalue(Tag<std::decay_t<Subject>>(*env, *subject)), AsLvalue(Tag<std::decay_t<Args>>(*env, args))...));
111 };
112
113 return MakeNativeMethod(name, TypeSignature<RemoveUniqueType<R> (std::decay_t<Args>...)>()(), wrapper);
114 }
115 };
116
117 template < class T, class Subject, class... Args >
118 struct NativeMethodMaker< void (T::*)(JNIEnv&, Subject, Args...) const >
119 {
120 template < class M >
121 auto operator()(const char* name, const M& m)
122 {
123 static M method(m);
124
126 {
127 method(*env, AsLvalue(Tag<std::decay_t<Subject>>(*env, *subject)), AsLvalue(Tag<std::decay_t<Args>>(*env, args))...);
128 };
129
130 return MakeNativeMethod(name, TypeSignature<void (std::decay_t<Args>...)>()(), wrapper);
131 }
132 };
133
134 template < class M >
135 auto MakeNativeMethod(const char* name, const M& m)
136 {
138 }
139
140
142
143 template < class R, class Subject, class... Args, R (*method)(JNIEnv&, Subject, Args...) >
144 struct NativeMethodMaker< R (JNIEnv&, Subject, Args...), method >
145 {
146 auto operator()(const char* name)
147 {
149 {
150 return ReleaseUnique(method(*env, AsLvalue(Tag<std::decay_t<Subject>>(*env, *subject)), AsLvalue(Tag<std::decay_t<Args>>(*env, args))...));
151 };
152
153 return MakeNativeMethod(name, TypeSignature<RemoveUniqueType<R> (std::decay_t<Args>...)>()(), wrapper);
154 }
155 };
156
157 template < class Subject, class... Args, void (*method)(JNIEnv&, Subject, Args...) >
158 struct NativeMethodMaker< void (JNIEnv&, Subject, Args...), method >
159 {
160 auto operator()(const char* name)
161 {
163 {
164 method(*env, AsLvalue(Tag<std::decay_t<Subject>>(*env, *subject)), AsLvalue(Tag<std::decay_t<Args>>(*env, args))...);
165 };
166
167 return MakeNativeMethod(name, TypeSignature<void (std::decay_t<Args>...)>()(), wrapper);
168 }
169 };
170
171 template < class M, M method >
172 auto MakeNativeMethod(const char* name)
173 {
176 }
177
178
180
181 template < class L, class >
183
184 template < class L, class R, class P, class... Args >
185 class NativePeerLambdaMethod< L, R (L::*)(JNIEnv&, P&, Args...) const >
186 {
187 private:
188 const char* name;
189 L lambda;
190
191 public:
192 NativePeerLambdaMethod(const char* n, const L& l)
193 : name(n), lambda(l)
194 {}
195
198 {
199 auto wrapper = [field, lambda = lambda] (JNIEnv& env, Object<TagType>& obj, Args... args)
200 {
201 return lambda(env, *reinterpret_cast<P*>(obj.Get(env, field)), args...);
202 };
203
204 return MakeNativeMethod(name, wrapper);
205 }
206 };
207
208 template < class L >
209 auto MakeNativePeerMethod(const char* name, const L& lambda,
210 std::enable_if_t< std::is_class<L>::value >* = nullptr)
211 {
213 }
214
215
217
218 template < class M, M* >
220
221 template < class R, class P, class... Args, R (*method)(JNIEnv&, P&, Args...) >
223 {
224 private:
225 const char* name;
226
227 public:
229 : name(n)
230 {}
231
234 {
235 auto wrapper = [field] (JNIEnv& env, Object<TagType>& obj, Args... args)
236 {
237 return method(env, *reinterpret_cast<P*>(obj.Get(env, field)), args...);
238 };
239
240 return MakeNativeMethod(name, wrapper);
241 }
242 };
243
244 template < class M, M method >
245 auto MakeNativePeerMethod(const char* name,
246 std::enable_if_t< !std::is_member_function_pointer<M>::value >* = nullptr)
247 {
250 }
251
252
254
255 template < class M, M >
257
258 template < class R, class P, class... Args, R (P::*method)(JNIEnv&, Args...) >
260 {
261 private:
262 const char* name;
263
264 public:
266 : name(n)
267 {}
268
271 {
272 auto wrapper = [field] (JNIEnv& env, Object<TagType>& obj, Args... args)
273 {
274 return (reinterpret_cast<P*>(obj.Get(env, field))->*method)(env, args...);
275 };
276
277 return MakeNativeMethod(name, wrapper);
278 }
279 };
280
281 template < class M, M method >
282 auto MakeNativePeerMethod(const char* name,
283 std::enable_if_t< std::is_member_function_pointer<M>::value >* = nullptr)
284 {
286 }
287
288
310 template < class Peer, class TagType, class... Methods >
312 {
313 static Field<TagType, jni::jlong> field { env, clazz, fieldName };
314 RegisterNatives(env, *clazz, methods.template operator()<Peer>(field)...);
315 }
316
317 template < class Peer, class TagType, class >
319
320 template < class Peer, class TagType, class... Args >
321 struct NativePeerHelper< Peer, TagType, std::unique_ptr<Peer> (JNIEnv&, Args...) >
322 {
323 using UniquePeer = std::unique_ptr<Peer>;
325
326 auto MakeInitializer(const Field<TagType, jlong>& field, const char* name, Initializer* initializer) const
327 {
328 auto wrapper = [field, initializer] (JNIEnv& e, Object<TagType>& obj, std::decay_t<Args>&... args)
329 {
330 UniquePeer previous(reinterpret_cast<Peer*>(obj.Get(e, field)));
332 obj.Set(e, field, reinterpret_cast<jlong>(instance.get()));
333 instance.release();
334 };
335
336 return MakeNativeMethod(name, wrapper);
337 }
338
339 auto MakeFinalizer(const Field<TagType, jlong>& field, const char* name) const
340 {
341 auto wrapper = [field] (JNIEnv& e, Object<TagType>& obj)
342 {
343 UniquePeer instance(reinterpret_cast<Peer*>(obj.Get(e, field)));
344 if (instance) obj.Set(e, field, jlong(0));
345 instance.reset();
346 };
347
348 return MakeNativeMethod(name, wrapper);
349 }
350 };
351
352 template < class Peer, class TagType, class Initializer, class... Methods >
354 Initializer initialize,
355 const char* initializeMethodName,
356 const char* finalizeMethodName,
357 Methods&&... methods)
358 {
359 static Field<TagType, jlong> field { env, clazz, fieldName };
360
363
365 helper.MakeInitializer(field, initializeMethodName, initialize),
366 helper.MakeFinalizer(field, finalizeMethodName),
367 methods.template operator()<Peer>(field)...);
368 }
369
370 // Like std::make_unique, but with non-universal reference arguments, so it can be
371 // explicitly specialized (jni::MakePeer<Peer, jni::jboolean, ...>).
372 template < class Peer, class... Args >
373 std::unique_ptr<Peer> MakePeer(jni::JNIEnv& env, Args... args)
374 {
375 return std::make_unique<Peer>(env, args...);
376 }
377 }
Definition class.hpp:18
Definition field.hpp:13
NativePeerFunctionPointerMethod(const char *n)
Definition native_method.hpp:228
auto operator()(const Field< TagType, jlong > &field)
Definition native_method.hpp:233
High-level peer, function pointer.
Definition native_method.hpp:219
auto operator()(const Field< TagType, jlong > &field)
Definition native_method.hpp:197
NativePeerLambdaMethod(const char *n, const L &l)
Definition native_method.hpp:192
High-level peer, lambda.
Definition native_method.hpp:182
auto operator()(const Field< TagType, jlong > &field)
Definition native_method.hpp:270
NativePeerMemberFunctionMethod(const char *n)
Definition native_method.hpp:265
High-level peer, member function pointer.
Definition native_method.hpp:256
Definition object.hpp:45
Definition advanced_ownership.hpp:6
auto Tag(JNIEnv &, T primitive) -> std::enable_if_t< IsPrimitive< T >::value, T >
Definition tagging.hpp:94
void ThrowJavaError(JNIEnv &env, std::exception_ptr e)
Definition errors.hpp:101
decltype(Untag(std::declval< T >())) UntaggedType
Definition tagging.hpp:130
typename RemoveUnique< T >::Type RemoveUniqueType
Definition unique.hpp:139
void RegisterNativePeer(JNIEnv &env, const Class< TagType > &clazz, const char *fieldName, Methods &&... methods)
Definition native_method.hpp:311
T & AsLvalue(T &&x)
Definition traits.hpp:33
auto MakeNativePeerMethod(const char *name, const L &lambda, std::enable_if_t< std::is_class< L >::value > *=nullptr)
Definition native_method.hpp:209
jarray< E > & NewArray(JNIEnv &env, jsize length)
Definition functions.hpp:472
void RegisterNatives(JNIEnv &env, jclass &clazz, const Methods &... methods)
Definition functions.hpp:573
auto ReleaseUnique(T primitive)
Definition unique.hpp:143
auto MakeNativeMethod(const char *name, const char *sig, const M &m, std::enable_if_t< std::is_class< M >::value > *=nullptr)
Low-level, lambda.
Definition native_method.hpp:45
std::unique_ptr< Peer > MakePeer(jni::JNIEnv &env, Args... args)
Definition native_method.hpp:373
Definition errors.hpp:10
Definition types.hpp:64
auto operator()(const char *name)
Definition native_method.hpp:146
auto operator()(const char *name, const M &m)
Definition native_method.hpp:104
auto operator()(const char *name)
Definition native_method.hpp:160
auto operator()(const char *name, const M &m)
Definition native_method.hpp:121
High-level, lambda.
Definition native_method.hpp:98
R ResultType
Definition native_method.hpp:22
R(Args...) Type
Definition native_method.hpp:21
Definition native_method.hpp:16
auto MakeInitializer(const Field< TagType, jlong > &field, const char *name, Initializer *initializer) const
Definition native_method.hpp:326
UniquePeer(JNIEnv &, Args...) Initializer
Definition native_method.hpp:324
std::unique_ptr< Peer > UniquePeer
Definition native_method.hpp:323
auto MakeFinalizer(const Field< TagType, jlong > &field, const char *name) const
Definition native_method.hpp:339
Definition native_method.hpp:318
Definition tagging.hpp:13