14
14
15
15
namespace jni
16
16
{
17
- // / Low-level
18
-
19
17
template < class M , class Enable = void >
20
- struct FunctionTypeTraits ;
18
+ struct NativeMethodTraits ;
21
19
22
20
template < class R , class ... Args >
23
- struct FunctionTypeTraits < R (Args...) >
21
+ struct NativeMethodTraits < R (Args...) >
24
22
{
25
23
using Type = R (Args...);
26
24
using ResultType = R;
27
25
};
28
26
29
27
template < class R , class ... Args >
30
- struct FunctionTypeTraits < R (*)(Args...) >
31
- : FunctionTypeTraits < R (Args...) > {};
28
+ struct NativeMethodTraits < R (*)(Args...) >
29
+ : NativeMethodTraits < R (Args...) > {};
32
30
33
31
template < class T , class R , class ... Args >
34
- struct FunctionTypeTraits < R (T::*)(Args...) const >
35
- : FunctionTypeTraits < R (Args...) > {};
32
+ struct NativeMethodTraits < R (T::*)(Args...) const >
33
+ : NativeMethodTraits < R (Args...) > {};
36
34
37
35
template < class T , class R , class ... Args >
38
- struct FunctionTypeTraits < R (T::*)(Args...) >
39
- : FunctionTypeTraits < R (Args...) > {};
36
+ struct NativeMethodTraits < R (T::*)(Args...) >
37
+ : NativeMethodTraits < R (Args...) > {};
40
38
41
39
template < class M >
42
- struct FunctionTypeTraits < M, std::enable_if_t < std::is_class<M>::value > >
43
- : FunctionTypeTraits< decltype (&M::operator ()) > {};
40
+ struct NativeMethodTraits < M, std::enable_if_t < std::is_class<M>::value > >
41
+ : NativeMethodTraits< decltype (&M::operator ()) > {};
42
+
43
+
44
+ // / Low-level, lambda
44
45
45
46
template < class M >
46
47
auto MakeNativeMethod (const char * name, const char * sig, const M& m,
47
48
std::enable_if_t < std::is_class<M>::value >* = 0 )
48
49
{
49
- using FunctionType = typename FunctionTypeTraits <M>::Type;
50
- using ResultType = typename FunctionTypeTraits <M>::ResultType;
50
+ using FunctionType = typename NativeMethodTraits <M>::Type;
51
+ using ResultType = typename NativeMethodTraits <M>::ResultType;
51
52
52
53
static FunctionType* method = m;
53
54
@@ -67,11 +68,14 @@ namespace jni
67
68
return JNINativeMethod< FunctionType > { name, sig, wrapper };
68
69
}
69
70
71
+
72
+ // / Low-level, function pointer
73
+
70
74
template < class M , M method >
71
75
auto MakeNativeMethod (const char * name, const char * sig)
72
76
{
73
- using FunctionType = typename FunctionTypeTraits <M>::Type;
74
- using ResultType = typename FunctionTypeTraits <M>::ResultType;
77
+ using FunctionType = typename NativeMethodTraits <M>::Type;
78
+ using ResultType = typename NativeMethodTraits <M>::ResultType;
75
79
76
80
auto wrapper = [] (JNIEnv* env, auto ... args)
77
81
{
@@ -90,7 +94,7 @@ namespace jni
90
94
}
91
95
92
96
93
- // / High-level
97
+ // / High-level, lambda
94
98
95
99
template < class T , T... >
96
100
struct NativeMethodMaker ;
@@ -103,96 +107,156 @@ namespace jni
103
107
{
104
108
static M method (m);
105
109
106
- auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args)
110
+ auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args) -> UntaggedType<R>
107
111
{
108
- return Untag ( method (*env, Tag<Subject>(*subject), Tag<Args>(args)...) );
112
+ return method (*env, Tag<Subject>(*subject), Tag<Args>(args)...);
109
113
};
110
114
111
115
return MakeNativeMethod (name, TypeSignature<R (Args...)>()(), wrapper);
112
116
}
113
117
};
114
118
115
- template < class T , class Subject , class ... Args >
116
- struct NativeMethodMaker < void (T::*)(JNIEnv&, Subject, Args...) const >
117
- {
118
- template < class M >
119
- auto operator ()(const char * name, const M& m)
120
- {
121
- static M method (m);
122
-
123
- auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args)
124
- {
125
- method (*env, Tag<Subject>(*subject), Tag<Args>(args)...);
126
- };
127
-
128
- return MakeNativeMethod (name, TypeSignature<void (Args...)>()(), wrapper);
129
- }
130
- };
131
-
132
119
template < class M >
133
120
auto MakeNativeMethod (const char * name, const M& m)
134
121
{
135
122
return NativeMethodMaker<decltype (&M::operator ())>()(name, m);
136
123
}
137
124
125
+
126
+ // / High-level, function pointer
127
+
138
128
template < class R , class Subject , class ... Args, R (*method)(JNIEnv&, Subject, Args...) >
139
129
struct NativeMethodMaker < R (JNIEnv&, Subject, Args...), method >
140
130
{
141
131
auto operator ()(const char * name)
142
132
{
143
- auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args)
133
+ auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args) -> UntaggedType<R>
144
134
{
145
- return Untag ( method (*env, Tag<Subject>(*subject), Tag<Args>(args)...) );
135
+ return method (*env, Tag<Subject>(*subject), Tag<Args>(args)...);
146
136
};
147
137
148
138
return MakeNativeMethod (name, TypeSignature<R (Args...)>()(), wrapper);
149
139
}
150
140
};
151
141
152
- template < class Subject , class ... Args, void (* method)(JNIEnv&, Subject, Args...) >
153
- struct NativeMethodMaker < void (JNIEnv&, Subject, Args...), method >
142
+ template < class M , M method >
143
+ auto MakeNativeMethod ( const char * name)
154
144
{
155
- auto operator ()(const char * name)
156
- {
157
- auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args)
145
+ using FunctionType = typename NativeMethodTraits<M>::Type;
146
+ return NativeMethodMaker<FunctionType, method>()(name);
147
+ }
148
+
149
+
150
+ // / High-level peer, lambda
151
+
152
+ template < class L , class >
153
+ class NativePeerLambdaMethod ;
154
+
155
+ template < class L , class R , class P , class ... Args >
156
+ class NativePeerLambdaMethod < L, R (L::*)(JNIEnv&, P&, Args...) const >
157
+ {
158
+ private:
159
+ const char * name;
160
+ L lambda;
161
+
162
+ public:
163
+ NativePeerLambdaMethod (const char * n, const L& l)
164
+ : name(n), lambda(l)
165
+ {}
166
+
167
+ template < class Peer , class TagType , class = std::enable_if_t < std::is_same<P, Peer>::value > >
168
+ auto operator ()(const Field<TagType, jlong>& field)
158
169
{
159
- method (*env, Tag<Subject>(*subject), Tag<Args>(args)...);
160
- };
170
+ auto wrapper = [field, lambda = lambda] (JNIEnv& env, Object<TagType> obj, Args... args)
171
+ {
172
+ return lambda (env, *reinterpret_cast <P*>(obj.Get (env, field)), std::move (args)...);
173
+ };
161
174
162
- return MakeNativeMethod (name, TypeSignature<void (Args...)>()(), wrapper);
163
- }
175
+ return MakeNativeMethod (name, wrapper);
176
+ }
177
+ };
178
+
179
+ template < class L >
180
+ auto MakeNativePeerMethod (const char * name, const L& lambda,
181
+ std::enable_if_t < std::is_class<L>::value >* = 0 )
182
+ {
183
+ return NativePeerLambdaMethod<L, decltype (&L::operator ())>(name, lambda);
184
+ }
185
+
186
+
187
+ // / High-level peer, function pointer
188
+
189
+ template < class M , M >
190
+ class NativePeerFunctionPointerMethod ;
191
+
192
+ template < class R , class P , class ... Args, R (*method)(JNIEnv&, P&, Args...) >
193
+ class NativePeerFunctionPointerMethod < R (JNIEnv&, P&, Args...), method >
194
+ {
195
+ private:
196
+ const char * name;
197
+
198
+ public:
199
+ NativePeerFunctionPointerMethod (const char * n)
200
+ : name(n)
201
+ {}
202
+
203
+ template < class Peer , class TagType , class = std::enable_if_t < std::is_same<P, Peer>::value > >
204
+ auto operator ()(const Field<TagType, jlong>& field)
205
+ {
206
+ auto wrapper = [field] (JNIEnv& env, Object<TagType> obj, Args... args)
207
+ {
208
+ return method (env, *reinterpret_cast <P*>(obj.Get (env, field)), std::move (args)...);
209
+ };
210
+
211
+ return MakeNativeMethod (name, wrapper);
212
+ }
164
213
};
165
214
166
215
template < class M , M method >
167
- auto MakeNativeMethod (const char * name)
216
+ auto MakeNativePeerMethod (const char * name,
217
+ std::enable_if_t < !std::is_member_function_pointer<M>::value >* = 0 )
168
218
{
169
- using FunctionType = typename FunctionTypeTraits <M>::Type;
170
- return NativeMethodMaker <FunctionType, method>() (name);
219
+ using FunctionType = typename NativeMethodTraits <M>::Type;
220
+ return NativePeerFunctionPointerMethod <FunctionType, method>(name);
171
221
}
172
222
173
223
224
+ // / High-level peer, member function pointer
225
+
174
226
template < class M , M >
175
- class NativePeerMethod ;
227
+ class NativePeerMemberFunctionMethod ;
176
228
177
- template < class T , class R , class ... Args, R (T ::*method)(JNIEnv&, Args...) >
178
- class NativePeerMethod < R (T ::*)(JNIEnv&, Args...), method >
229
+ template < class R , class P , class ... Args, R (P ::*method)(JNIEnv&, Args...) >
230
+ class NativePeerMemberFunctionMethod < R (P ::*)(JNIEnv&, Args...), method >
179
231
{
180
232
private:
181
233
const char * name;
182
234
183
235
public:
184
- NativePeerMethod (const char * n)
236
+ NativePeerMemberFunctionMethod (const char * n)
185
237
: name(n)
186
238
{}
187
239
188
- template < class TagType >
240
+ template < class Peer , class TagType , class = std:: enable_if_t < std::is_same<P, Peer>::value > >
189
241
auto operator ()(const Field<TagType, jlong>& field)
190
242
{
191
- return MakeNativeMethod (name, [&field] (JNIEnv& env, Object<TagType> obj, Args... args)
192
- { return (reinterpret_cast <T*>(obj.Get (env, field))->*method)(env, std::move (args)...); });
243
+ auto wrapper = [field] (JNIEnv& env, Object<TagType> obj, Args... args)
244
+ {
245
+ return (reinterpret_cast <P*>(obj.Get (env, field))->*method)(env, std::move (args)...);
246
+ };
247
+
248
+ return MakeNativeMethod (name, wrapper);
193
249
}
194
250
};
195
251
252
+ template < class M , M method >
253
+ auto MakeNativePeerMethod (const char * name,
254
+ std::enable_if_t < std::is_member_function_pointer<M>::value >* = 0 )
255
+ {
256
+ return NativePeerMemberFunctionMethod<M, method>(name);
257
+ }
258
+
259
+
196
260
/* *
197
261
* A registration function for native methods on a "native peer": a long-lived native
198
262
* object corresponding to a Java object, usually created when the Java object is created
@@ -214,43 +278,40 @@ namespace jni
214
278
* For an example of all of the above, see the `examples` directory.
215
279
*/
216
280
217
- template < class TagType , class ... Methods >
281
+ template < class Peer , class TagType , class ... Methods >
218
282
void RegisterNativePeer (JNIEnv& env, const Class<TagType>& clazz, const char * fieldName, Methods&&... methods)
219
283
{
220
284
static Field<TagType, jni::jlong> field { env, clazz, fieldName };
221
- RegisterNatives (env, clazz, methods (field)...);
285
+ RegisterNatives (env, clazz, methods. template operator ()<Peer> (field)...);
222
286
}
223
287
224
- template < class TagType , class Constructor , class ... Methods >
288
+ template < class Peer , class TagType , class Constructor , class ... Methods >
225
289
void RegisterNativePeer (JNIEnv& env, const Class<TagType>& clazz, const char * fieldName,
226
290
Constructor constructor,
227
291
const char * initializeMethodName,
228
292
const char * finalizeMethodName,
229
293
Methods&&... methods)
230
294
{
231
- using UniquePtr = decltype (constructor ());
232
- using Pointer = typename UniquePtr::pointer;
233
-
234
295
static Field<TagType, jlong> field { env, clazz, fieldName };
235
296
236
297
auto finalize = [] (JNIEnv& e, Object<TagType> obj)
237
298
{
238
- UniquePtr instance (reinterpret_cast <Pointer >(obj.Get (e, field)));
299
+ std::unique_ptr<Peer> instance (reinterpret_cast <Peer* >(obj.Get (e, field)));
239
300
if (instance) obj.Set (e, field, jlong (0 ));
240
301
instance.reset ();
241
302
};
242
303
243
304
auto initialize = [constructor] (JNIEnv& e, Object<TagType> obj)
244
305
{
245
- UniquePtr previous (reinterpret_cast <Pointer >(obj.Get (e, field)));
246
- UniquePtr instance (constructor ());
306
+ std::unique_ptr<Peer> previous (reinterpret_cast <Peer* >(obj.Get (e, field)));
307
+ std::unique_ptr<Peer> instance (constructor ());
247
308
obj.Set (e, field, reinterpret_cast <jlong>(instance.get ()));
248
309
instance.release ();
249
310
};
250
311
251
312
RegisterNatives (env, clazz,
252
313
MakeNativeMethod (initializeMethodName, initialize),
253
314
MakeNativeMethod (finalizeMethodName, finalize),
254
- methods (field)...);
315
+ methods. template operator ()<Peer> (field)...);
255
316
}
256
317
}
0 commit comments