Skip to content

Commit 13ea409

Browse files
committed
Yet more iteration on registration
1 parent 8d042ae commit 13ea409

File tree

6 files changed

+166
-85
lines changed

6 files changed

+166
-85
lines changed

examples/native_peer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*)
1717

1818
jni::JNIEnv& env { jni::GetEnv(*vm) };
1919

20-
#define METHOD(MethodPtr, name) jni::NativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
20+
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
2121

22-
jni::RegisterNativePeer(env, jni::Class<Calculator>::Find(env), "peer",
22+
jni::RegisterNativePeer<Calculator>(env, jni::Class<Calculator>::Find(env), "peer",
2323
std::make_unique<Calculator>,
2424
"initialize",
2525
"finalize",

include/jni/array.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ namespace jni
3434

3535
explicit operator bool() const { return array; }
3636

37+
operator UntaggedType*() const { return array; }
3738
UntaggedType& operator*() const { return *array; }
3839
UntaggedType* Get() const { return array; }
3940

@@ -99,6 +100,7 @@ namespace jni
99100

100101
explicit operator bool() const { return array; }
101102

103+
operator UntaggedType*() const { return array; }
102104
UntaggedType& operator*() const { return *array; }
103105
UntaggedType* Get() const { return array; }
104106

include/jni/native_method.hpp

Lines changed: 128 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -14,40 +14,41 @@
1414

1515
namespace jni
1616
{
17-
/// Low-level
18-
1917
template < class M, class Enable = void >
20-
struct FunctionTypeTraits;
18+
struct NativeMethodTraits;
2119

2220
template < class R, class... Args >
23-
struct FunctionTypeTraits< R (Args...) >
21+
struct NativeMethodTraits< R (Args...) >
2422
{
2523
using Type = R (Args...);
2624
using ResultType = R;
2725
};
2826

2927
template < class R, class... Args >
30-
struct FunctionTypeTraits< R (*)(Args...) >
31-
: FunctionTypeTraits< R (Args...) > {};
28+
struct NativeMethodTraits< R (*)(Args...) >
29+
: NativeMethodTraits< R (Args...) > {};
3230

3331
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...) > {};
3634

3735
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...) > {};
4038

4139
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
4445

4546
template < class M >
4647
auto MakeNativeMethod(const char* name, const char* sig, const M& m,
4748
std::enable_if_t< std::is_class<M>::value >* = 0)
4849
{
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;
5152

5253
static FunctionType* method = m;
5354

@@ -67,11 +68,14 @@ namespace jni
6768
return JNINativeMethod< FunctionType > { name, sig, wrapper };
6869
}
6970

71+
72+
/// Low-level, function pointer
73+
7074
template < class M, M method >
7175
auto MakeNativeMethod(const char* name, const char* sig)
7276
{
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;
7579

7680
auto wrapper = [] (JNIEnv* env, auto... args)
7781
{
@@ -90,7 +94,7 @@ namespace jni
9094
}
9195

9296

93-
/// High-level
97+
/// High-level, lambda
9498

9599
template < class T, T... >
96100
struct NativeMethodMaker;
@@ -103,96 +107,156 @@ namespace jni
103107
{
104108
static M method(m);
105109

106-
auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args)
110+
auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args) -> UntaggedType<R>
107111
{
108-
return Untag(method(*env, Tag<Subject>(*subject), Tag<Args>(args)...));
112+
return method(*env, Tag<Subject>(*subject), Tag<Args>(args)...);
109113
};
110114

111115
return MakeNativeMethod(name, TypeSignature<R (Args...)>()(), wrapper);
112116
}
113117
};
114118

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-
132119
template < class M >
133120
auto MakeNativeMethod(const char* name, const M& m)
134121
{
135122
return NativeMethodMaker<decltype(&M::operator())>()(name, m);
136123
}
137124

125+
126+
/// High-level, function pointer
127+
138128
template < class R, class Subject, class... Args, R (*method)(JNIEnv&, Subject, Args...) >
139129
struct NativeMethodMaker< R (JNIEnv&, Subject, Args...), method >
140130
{
141131
auto operator()(const char* name)
142132
{
143-
auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args)
133+
auto wrapper = [] (JNIEnv* env, UntaggedType<Subject> subject, UntaggedType<Args>... args) -> UntaggedType<R>
144134
{
145-
return Untag(method(*env, Tag<Subject>(*subject), Tag<Args>(args)...));
135+
return method(*env, Tag<Subject>(*subject), Tag<Args>(args)...);
146136
};
147137

148138
return MakeNativeMethod(name, TypeSignature<R (Args...)>()(), wrapper);
149139
}
150140
};
151141

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)
154144
{
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)
158169
{
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+
};
161174

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+
}
164213
};
165214

166215
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)
168218
{
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);
171221
}
172222

173223

224+
/// High-level peer, member function pointer
225+
174226
template < class M, M >
175-
class NativePeerMethod;
227+
class NativePeerMemberFunctionMethod;
176228

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 >
179231
{
180232
private:
181233
const char* name;
182234

183235
public:
184-
NativePeerMethod(const char* n)
236+
NativePeerMemberFunctionMethod(const char* n)
185237
: name(n)
186238
{}
187239

188-
template < class TagType >
240+
template < class Peer, class TagType, class = std::enable_if_t< std::is_same<P, Peer>::value > >
189241
auto operator()(const Field<TagType, jlong>& field)
190242
{
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);
193249
}
194250
};
195251

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+
196260
/**
197261
* A registration function for native methods on a "native peer": a long-lived native
198262
* object corresponding to a Java object, usually created when the Java object is created
@@ -214,43 +278,40 @@ namespace jni
214278
* For an example of all of the above, see the `examples` directory.
215279
*/
216280

217-
template < class TagType, class... Methods >
281+
template < class Peer, class TagType, class... Methods >
218282
void RegisterNativePeer(JNIEnv& env, const Class<TagType>& clazz, const char* fieldName, Methods&&... methods)
219283
{
220284
static Field<TagType, jni::jlong> field { env, clazz, fieldName };
221-
RegisterNatives(env, clazz, methods(field)...);
285+
RegisterNatives(env, clazz, methods.template operator()<Peer>(field)...);
222286
}
223287

224-
template < class TagType, class Constructor, class... Methods >
288+
template < class Peer, class TagType, class Constructor, class... Methods >
225289
void RegisterNativePeer(JNIEnv& env, const Class<TagType>& clazz, const char* fieldName,
226290
Constructor constructor,
227291
const char* initializeMethodName,
228292
const char* finalizeMethodName,
229293
Methods&&... methods)
230294
{
231-
using UniquePtr = decltype(constructor());
232-
using Pointer = typename UniquePtr::pointer;
233-
234295
static Field<TagType, jlong> field { env, clazz, fieldName };
235296

236297
auto finalize = [] (JNIEnv& e, Object<TagType> obj)
237298
{
238-
UniquePtr instance(reinterpret_cast<Pointer>(obj.Get(e, field)));
299+
std::unique_ptr<Peer> instance(reinterpret_cast<Peer*>(obj.Get(e, field)));
239300
if (instance) obj.Set(e, field, jlong(0));
240301
instance.reset();
241302
};
242303

243304
auto initialize = [constructor] (JNIEnv& e, Object<TagType> obj)
244305
{
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());
247308
obj.Set(e, field, reinterpret_cast<jlong>(instance.get()));
248309
instance.release();
249310
};
250311

251312
RegisterNatives(env, clazz,
252313
MakeNativeMethod(initializeMethodName, initialize),
253314
MakeNativeMethod(finalizeMethodName, finalize),
254-
methods(field)...);
315+
methods.template operator()<Peer>(field)...);
255316
}
256317
}

include/jni/object.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ namespace jni
5050

5151
explicit operator bool() const { return obj; }
5252

53+
operator UntaggedObjectType*() const { return obj; }
5354
UntaggedObjectType& operator*() const { return *obj; }
5455
UntaggedObjectType* Get() const { return obj; }
5556

include/jni/tagging.hpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,19 @@ namespace jni
4242
return t.Get();
4343
}
4444

45+
46+
template < class T >
47+
struct UntaggedTypeTraits
48+
{
49+
using Type = decltype(Untag(std::declval<T>()));
50+
};
51+
52+
template <>
53+
struct UntaggedTypeTraits<void>
54+
{
55+
using Type = void;
56+
};
57+
4558
template < class T >
46-
using UntaggedType = decltype(Untag(std::declval<T>()));
59+
using UntaggedType = typename UntaggedTypeTraits<T>::Type;
4760
}

0 commit comments

Comments
 (0)