Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 5807ae2

Browse files
committedSep 4, 2018
Extend automatic derived-to-base conversion
1 parent eda4979 commit 5807ae2

File tree

8 files changed

+136
-105
lines changed

8 files changed

+136
-105
lines changed
 

‎include/jni/array.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ namespace jni
9595
using TagType = TheTag;
9696
using ElementType = Object<TagType>;
9797
using UntaggedType = jarray<jobject>;
98-
using UntaggedElementType = typename ElementType::UntaggedObjectType;
98+
using UntaggedElementType = typename ElementType::UntaggedType;
9999

100100
private:
101101
UntaggedType* array = nullptr;

‎include/jni/boxing.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ namespace jni
99
template < class > struct Unboxer;
1010

1111
template < class Unboxed >
12-
auto Box(JNIEnv& env, Unboxed&& unboxed)
12+
decltype(auto) Box(JNIEnv& env, Unboxed&& unboxed)
1313
{
1414
return Boxer<typename std::decay<Unboxed>::type>().Box(env, std::forward<Unboxed>(unboxed));
1515
}
1616

17-
template < class Tag >
18-
auto Unbox(JNIEnv& env, const Object<Tag>& boxed)
17+
template < class T >
18+
decltype(auto) Unbox(JNIEnv& env, const T& boxed)
1919
{
20-
return Unboxer<Tag>().Unbox(env, boxed);
20+
return Unboxer<typename T::TagType>().Unbox(env, boxed);
2121
}
2222

2323

@@ -99,7 +99,7 @@ namespace jni
9999
{
100100
Local<Object<Tag>> Box(JNIEnv& env, Unboxed unboxed) const
101101
{
102-
static auto klass = Class<Tag>::Singleton(env);
102+
static auto& klass = Class<Tag>::Singleton(env);
103103
static auto box = klass.template GetStaticMethod<Object<Tag> (Unboxed)>(env, Tag::BoxStaticMethodName());
104104
return klass.Call(env, box, unboxed);
105105
}
@@ -120,7 +120,7 @@ namespace jni
120120
{
121121
Unboxed Unbox(JNIEnv& env, const Object<Tag>& boxed) const
122122
{
123-
static auto klass = Class<Tag>::Singleton(env);
123+
static auto& klass = Class<Tag>::Singleton(env);
124124
static auto unbox = klass.template GetMethod<Unboxed ()>(env, Tag::UnboxMethodName());
125125
return boxed.Call(env, unbox);
126126
}

‎include/jni/class.hpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ namespace jni
1616
template < class TheTag >
1717
class Class
1818
{
19-
private:
19+
public:
2020
using TagType = TheTag;
21+
using UntaggedType = jclass;
2122

23+
private:
2224
jclass* clazz = nullptr;
2325

2426
protected:
@@ -66,7 +68,7 @@ namespace jni
6668
auto Get(JNIEnv& env, const StaticField<TagType, T>& field) const
6769
-> std::enable_if_t< !IsPrimitive<T>::value, Local<T> >
6870
{
69-
return Local<T>(env, reinterpret_cast<UntaggedType<T>>(jni::GetStaticField<jobject*>(env, *clazz, field)));
71+
return Local<T>(env, reinterpret_cast<typename T::UntaggedType*>(jni::GetStaticField<jobject*>(env, *clazz, field)));
7072
}
7173

7274
template < class T >
@@ -98,7 +100,7 @@ namespace jni
98100
&& !std::is_void<R>::value
99101
&& Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value, Local<R> >
100102
{
101-
return Local<R>(env, reinterpret_cast<UntaggedType<R>>(CallStaticMethod<jobject*>(env, *clazz, method, Untag(args)...)));
103+
return Local<R>(env, reinterpret_cast<typename R::UntaggedType*>(CallStaticMethod<jobject*>(env, *clazz, method, Untag(args)...)));
102104
}
103105

104106
template < class... ExpectedArgs, class... ActualArgs >

‎include/jni/native_method.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ namespace jni
200200
{
201201
auto wrapper = [field, lambda = lambda] (JNIEnv& env, Object<TagType>& obj, Args... args)
202202
{
203-
return lambda(env, *reinterpret_cast<P*>(obj.Get(env, field)), std::move(args)...);
203+
return lambda(env, *reinterpret_cast<P*>(obj.Get(env, field)), args...);
204204
};
205205

206206
return MakeNativeMethod(name, wrapper);
@@ -236,7 +236,7 @@ namespace jni
236236
{
237237
auto wrapper = [field] (JNIEnv& env, Object<TagType>& obj, Args... args)
238238
{
239-
return method(env, *reinterpret_cast<P*>(obj.Get(env, field)), std::move(args)...);
239+
return method(env, *reinterpret_cast<P*>(obj.Get(env, field)), args...);
240240
};
241241

242242
return MakeNativeMethod(name, wrapper);
@@ -273,7 +273,7 @@ namespace jni
273273
{
274274
auto wrapper = [field] (JNIEnv& env, Object<TagType>& obj, Args... args)
275275
{
276-
return (reinterpret_cast<P*>(obj.Get(env, field))->*method)(env, std::move(args)...);
276+
return (reinterpret_cast<P*>(obj.Get(env, field))->*method)(env, args...);
277277
};
278278

279279
return MakeNativeMethod(name, wrapper);
@@ -330,7 +330,7 @@ namespace jni
330330
auto wrapper = [field, initializer] (JNIEnv& e, Object<TagType>& obj, std::decay_t<Args>&... args)
331331
{
332332
UniquePeer previous(reinterpret_cast<Peer*>(obj.Get(e, field)));
333-
UniquePeer instance(initializer(e, std::move(args)...));
333+
UniquePeer instance(initializer(e, args...));
334334
obj.Set(e, field, reinterpret_cast<jlong>(instance.get()));
335335
instance.release();
336336
};

‎include/jni/object.hpp

Lines changed: 81 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -11,88 +11,126 @@ namespace jni
1111
template < class TheTag, class > class Field;
1212
template < class TheTag, class > class Method;
1313

14-
struct ObjectTag { static constexpr auto Name() { return "java/lang/Object"; } };
14+
struct ObjectTag
15+
{
16+
static constexpr auto Name() { return "java/lang/Object"; }
17+
};
18+
19+
struct StringTag
20+
{
21+
using SuperTag = ObjectTag;
22+
static constexpr auto Name() { return "java/lang/String"; }
23+
};
24+
25+
class ObjectBase
26+
{
27+
protected:
28+
jobject* ptr = nullptr;
29+
30+
explicit ObjectBase(std::nullptr_t = nullptr)
31+
{}
32+
33+
explicit ObjectBase(jobject* p)
34+
: ptr(p)
35+
{}
36+
37+
~ObjectBase() = default;
38+
39+
void reset(jobject* p) { ptr = p; }
40+
41+
public:
42+
explicit operator bool() const { return ptr; }
43+
44+
friend bool operator==(const ObjectBase& a, const ObjectBase& b) { return a.ptr == b.ptr; }
45+
friend bool operator!=(const ObjectBase& a, const ObjectBase& b) { return !( a == b ); }
46+
47+
template < class OtherTag >
48+
bool IsInstanceOf(JNIEnv& env, const Class<OtherTag>& clazz) const
49+
{
50+
return jni::IsInstanceOf(env, ptr, clazz);
51+
}
52+
};
53+
54+
template < class Tag, class Enable = void >
55+
struct SuperObject;
1556

16-
template < class TagType >
17-
struct UntaggedObjectType { using Type = jobject; };
57+
template < class Tag >
58+
struct SuperObject<Tag, typename Tag::SuperTag>
59+
{
60+
using Type = Object<typename Tag::SuperTag>;
61+
};
62+
63+
template < class Tag >
64+
struct SuperObject<Tag>
65+
{
66+
using Type = Object<ObjectTag>;
67+
};
68+
69+
template <>
70+
struct SuperObject<ObjectTag>
71+
{
72+
using Type = ObjectBase;
73+
};
1874

1975
template < class TheTag = ObjectTag >
20-
class Object
76+
class Object : public SuperObject<TheTag>::Type
2177
{
2278
public:
2379
using TagType = TheTag;
24-
using UntaggedObjectType = typename UntaggedObjectType<TagType>::Type;
25-
26-
private:
27-
UntaggedObjectType* obj = nullptr;
80+
using UntaggedType = std::conditional_t< std::is_same< TheTag, StringTag >::value, jstring, jobject >;
2881

2982
protected:
3083
explicit Object(std::nullptr_t = nullptr)
3184
{}
3285

33-
explicit Object(UntaggedObjectType* o)
34-
: obj(o)
86+
explicit Object(UntaggedType* p)
87+
: SuperObject<TagType>::Type(p)
3588
{}
3689

37-
Object(const Object& o)
38-
: obj(o.obj)
39-
{}
40-
41-
template < class Tag >
42-
Object(const Object<Tag>& o, std::enable_if_t< std::is_convertible<Tag, TagType>::value >* = nullptr)
43-
: obj(o.Get())
44-
{}
45-
46-
~Object() = default;
47-
90+
Object(const Object&) = delete;
4891
Object& operator=(const Object&) = delete;
49-
void reset(UntaggedObjectType* o) { obj = o; }
5092

5193
public:
52-
explicit operator bool() const { return obj; }
53-
54-
operator UntaggedObjectType*() const { return obj; }
55-
UntaggedObjectType& operator*() const { return *obj; }
56-
UntaggedObjectType* Get() const { return obj; }
94+
UntaggedType* Get() const { return reinterpret_cast<UntaggedType*>(this->ptr); }
5795

58-
friend bool operator==( const Object& a, const Object& b ) { return a.Get() == b.Get(); }
59-
friend bool operator!=( const Object& a, const Object& b ) { return !( a == b ); }
96+
operator UntaggedType*() const { return Get(); }
97+
UntaggedType& operator*() const { return *Get(); }
6098

6199
template < class T >
62100
auto Get(JNIEnv& env, const Field<TagType, T>& field) const
63101
-> std::enable_if_t< IsPrimitive<T>::value, T >
64102
{
65-
return GetField<T>(env, obj, field);
103+
return GetField<T>(env, this->ptr, field);
66104
}
67105

68106
template < class T >
69107
auto Get(JNIEnv& env, const Field<TagType, T>& field) const
70108
-> std::enable_if_t< !IsPrimitive<T>::value, Local<T> >
71109
{
72-
return Local<T>(env, reinterpret_cast<UntaggedType<T>>(GetField<jobject*>(env, obj, field)));
110+
return Local<T>(env, reinterpret_cast<typename T::UntaggedType*>(GetField<jobject*>(env, this->ptr, field)));
73111
}
74112

75113
template < class T >
76114
auto Set(JNIEnv& env, const Field<TagType, T>& field, T value) const
77115
-> std::enable_if_t< IsPrimitive<T>::value >
78116
{
79-
SetField<T>(env, obj, field, value);
117+
SetField<T>(env, this->ptr, field, value);
80118
}
81119

82120
template < class Expected, class Actual >
83121
auto Set(JNIEnv& env, const Field<TagType, Expected>& field, const Actual& value) const
84122
-> std::enable_if_t< !IsPrimitive<Expected>::value
85123
&& std::is_convertible<const Actual&, const Expected&>::value >
86124
{
87-
SetField<jobject*>(env, obj, field, value.Get());
125+
SetField<jobject*>(env, this->ptr, field, value.Get());
88126
}
89127

90128
template < class R, class... ExpectedArgs, class... ActualArgs >
91129
auto Call(JNIEnv& env, const Method<TagType, R (ExpectedArgs...)>& method, const ActualArgs&... args) const
92130
-> std::enable_if_t< IsPrimitive<R>::value
93131
&& Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value, R >
94132
{
95-
return CallMethod<R>(env, obj, method, Untag(args)...);
133+
return CallMethod<R>(env, this->ptr, method, Untag(args)...);
96134
}
97135

98136
template < class R, class... ExpectedArgs, class... ActualArgs >
@@ -101,22 +139,22 @@ namespace jni
101139
&& !std::is_void<R>::value
102140
&& Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value, Local<R> >
103141
{
104-
return Local<R>(env, reinterpret_cast<UntaggedType<R>>(CallMethod<jobject*>(env, obj, method, Untag(args)...)));
142+
return Local<R>(env, reinterpret_cast<typename R::UntaggedType*>(CallMethod<jobject*>(env, this->ptr, method, Untag(args)...)));
105143
}
106144

107145
template < class... ExpectedArgs, class... ActualArgs >
108146
auto Call(JNIEnv& env, const Method<TagType, void (ExpectedArgs...)>& method, const ActualArgs&... args) const
109147
-> std::enable_if_t< Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value >
110148
{
111-
CallMethod<void>(env, obj, method, Untag(args)...);
149+
CallMethod<void>(env, this->ptr, method, Untag(args)...);
112150
}
113151

114152
template < class R, class... ExpectedArgs, class... ActualArgs >
115153
auto CallNonvirtual(JNIEnv& env, const Class<TagType>& clazz, const Method<TagType, R (ExpectedArgs...)>& method, const ActualArgs&... args) const
116154
-> std::enable_if_t< IsPrimitive<R>::value
117155
&& Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value, R >
118156
{
119-
return CallNonvirtualMethod<R>(env, obj, clazz, method, Untag(args)...);
157+
return CallNonvirtualMethod<R>(env, this->ptr, clazz, method, Untag(args)...);
120158
}
121159

122160
template < class R, class... ExpectedArgs, class... ActualArgs >
@@ -125,37 +163,31 @@ namespace jni
125163
&& !std::is_void<R>::value
126164
&& Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value, Local<R> >
127165
{
128-
return Local<R>(env, reinterpret_cast<UntaggedType<R>>(CallNonvirtualMethod<jobject*>(env, obj, clazz, method, Untag(args)...)));
166+
return Local<R>(env, reinterpret_cast<typename R::UntaggedType*>(CallNonvirtualMethod<jobject*>(env, this->ptr, clazz, method, Untag(args)...)));
129167
}
130168

131169
template < class... ExpectedArgs, class... ActualArgs >
132170
auto CallNonvirtual(JNIEnv& env, const Class<TagType>& clazz, const Method<TagType, void (ExpectedArgs...)>& method, const ActualArgs&... args) const
133171
-> std::enable_if_t< Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value >
134172
{
135-
CallNonvirtualMethod<void>(env, obj, clazz, method, Untag(args)...);
173+
CallNonvirtualMethod<void>(env, this->ptr, clazz, method, Untag(args)...);
136174
}
137175

138176
template < template < RefDeletionMethod > class Deleter = DefaultRefDeleter >
139177
Global<Object<TagType>, Deleter> NewGlobalRef(JNIEnv& env) const
140178
{
141-
return Global<Object<TagType>, Deleter>(env, jni::NewGlobalRef(env, obj).release());
179+
return Global<Object<TagType>, Deleter>(env, reinterpret_cast<typename Object<TagType>::UntaggedType*>(jni::NewGlobalRef(env, this->ptr).release()));
142180
}
143181

144182
template < template < RefDeletionMethod > class Deleter = DefaultRefDeleter >
145183
Weak<Object<TagType>, Deleter> NewWeakGlobalRef(JNIEnv& env) const
146184
{
147-
return Weak<Object<TagType>, Deleter>(env, jni::NewWeakGlobalRef(env, obj).release());
185+
return Weak<Object<TagType>, Deleter>(env, reinterpret_cast<typename Object<TagType>::UntaggedType*>(jni::NewWeakGlobalRef(env, this->ptr).release()));
148186
}
149187

150188
Local<Object<TagType>> NewLocalRef(JNIEnv& env) const
151189
{
152-
return Local<Object<TagType>>(env, jni::NewLocalRef(env, obj).release());
153-
}
154-
155-
template < class OtherTag >
156-
bool IsInstanceOf(JNIEnv& env, const Class<OtherTag>& clazz) const
157-
{
158-
return jni::IsInstanceOf(env, obj, clazz);
190+
return Local<Object<TagType>>(env, reinterpret_cast<typename Object<TagType>::UntaggedType*>(jni::NewLocalRef(env, this->ptr).release()));
159191
}
160192
};
161193

@@ -166,6 +198,6 @@ namespace jni
166198
{
167199
ThrowNew(env, FindClass(env, "java/lang/ClassCastException"));
168200
}
169-
return Local<Object<OutTagType>>(env, reinterpret_cast<UntaggedType<Object<OutTagType>>>(object.NewLocalRef().release()));
201+
return Local<Object<OutTagType>>(env, reinterpret_cast<typename Object<OutTagType>::UntaggedType*>(object.NewLocalRef(env).release()));
170202
}
171203
}

‎include/jni/string.hpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,6 @@
1010

1111
namespace jni
1212
{
13-
struct StringTag : public ObjectTag { static constexpr auto Name() { return "java/lang/String"; } };
14-
15-
template <>
16-
struct UntaggedObjectType<StringTag> { using Type = jstring; };
17-
1813
using String = Object<StringTag>;
1914

2015
inline std::u16string MakeAnything(ThingToMake<std::u16string>, JNIEnv& env, const String& string)

‎include/jni/tagging.hpp

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,6 @@
66

77
namespace jni
88
{
9-
template < class T >
10-
auto Untag(T primitive)
11-
-> std::enable_if_t< IsPrimitive<T>::value, T >
12-
{
13-
return primitive;
14-
}
15-
16-
template < class T >
17-
auto Untag(const T& t)
18-
-> std::enable_if_t< !IsPrimitive<T>::value, decltype(t.Get()) >
19-
{
20-
return t.Get();
21-
}
22-
23-
template < class T >
24-
struct UntaggedTypeTraits
25-
{
26-
using Type = decltype(Untag(std::declval<T>()));
27-
};
28-
29-
template <>
30-
struct UntaggedTypeTraits<void>
31-
{
32-
using Type = void;
33-
};
34-
35-
template < class T >
36-
using UntaggedType = typename UntaggedTypeTraits<T>::Type;
37-
389
/*
3910
The interface for high-level references. Client code using the high-level API
4011
will most often work with values of this class template, using the following aliases:
@@ -79,12 +50,13 @@ namespace jni
7950

8051
public:
8152
using Base = T;
53+
using UntaggedType = typename T::UntaggedType;
8254

8355
explicit Tagged(std::nullptr_t ptr = nullptr)
8456
: T(ptr),
8557
deleter() {}
8658

87-
explicit Tagged(JNIEnv& env, UntaggedType<T> ptr)
59+
explicit Tagged(JNIEnv& env, UntaggedType* ptr)
8860
: T(ptr),
8961
deleter(env) {}
9062

@@ -109,19 +81,19 @@ namespace jni
10981
return *this;
11082
}
11183

112-
void reset(UntaggedType<T> ptr = nullptr)
84+
void reset(UntaggedType* ptr = nullptr)
11385
{
114-
UntaggedType<T> current = T::Get();
86+
UntaggedType* current = T::Get();
11587
T::reset(ptr);
11688
if (current)
11789
{
11890
get_deleter()(current);
11991
}
12092
}
12193

122-
UntaggedType<T> release()
94+
UntaggedType* release()
12395
{
124-
UntaggedType<T> current = T::Get();
96+
UntaggedType* current = T::Get();
12597
T::reset(nullptr);
12698
return current;
12799
}
@@ -214,6 +186,36 @@ namespace jni
214186
}
215187

216188

189+
template < class T >
190+
auto Untag(T primitive)
191+
-> std::enable_if_t< IsPrimitive<T>::value, T >
192+
{
193+
return primitive;
194+
}
195+
196+
template < class T >
197+
auto Untag(const T& t)
198+
-> std::enable_if_t< !IsPrimitive<T>::value, decltype(t.Get()) >
199+
{
200+
return t.Get();
201+
}
202+
203+
template < class T >
204+
struct UntaggedTypeTraits
205+
{
206+
using Type = decltype(Untag(std::declval<T>()));
207+
};
208+
209+
template <>
210+
struct UntaggedTypeTraits<void>
211+
{
212+
using Type = void;
213+
};
214+
215+
template < class T >
216+
using UntaggedType = typename UntaggedTypeTraits<T>::Type;
217+
218+
217219
template < class T >
218220
struct BaseTypeTraits
219221
{

‎include/jni/weak_reference.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ namespace jni
1818
Global<Object<WeakReferenceTag>, Deleter> reference;
1919

2020
public:
21-
WeakReference(JNIEnv& env, T referent)
21+
WeakReference(JNIEnv& env, const T& referent)
2222
{
2323
static auto& klass = Class<WeakReferenceTag>::Singleton(env);
2424
static auto constructor = klass.GetConstructor<Object<>>(env);
25-
reference = klass.New(env, constructor, Object<>(referent.Get())).template NewGlobalRef<Deleter>(env);
25+
reference = klass.New(env, constructor, referent).template NewGlobalRef<Deleter>(env);
2626
}
2727

2828
Local<T> get(JNIEnv& env)
@@ -34,7 +34,7 @@ namespace jni
3434

3535
static auto& klass = Class<WeakReferenceTag>::Singleton(env);
3636
static auto get = klass.template GetMethod<Object<> ()>(env, "get");
37-
return Local<T>(env, reinterpret_cast<UntaggedType<T>>(reference->Call(env, get).release()));
37+
return Local<T>(env, reinterpret_cast<typename T::UntaggedType*>(reference.Call(env, get).release()));
3838
}
3939
};
4040
}

0 commit comments

Comments
 (0)
Please sign in to comment.