Skip to content

Commit 8030424

Browse files
committed
Get/Set/Call methods need to be overloaded for reference types
1 parent 7a99cef commit 8030424

File tree

4 files changed

+123
-29
lines changed

4 files changed

+123
-29
lines changed

include/jni/class.hpp

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,45 @@ namespace jni
4141
}
4242

4343
template < class T >
44-
T Get(JNIEnv& env, const StaticField<TagType, T>& field) const
44+
auto Get(JNIEnv& env, const StaticField<TagType, T>& field) const
45+
-> std::enable_if_t< IsPrimitive<T>::value, T >
4546
{
46-
return Tag<T>(jni::GetStaticField<UntaggedType<T>>(env, clazz, field));
47+
return jni::GetStaticField<T>(env, clazz, field);
4748
}
4849

4950
template < class T >
50-
void Set(JNIEnv& env, const StaticField<TagType, T>& field, const T& value) const
51+
auto Get(JNIEnv& env, const StaticField<TagType, T>& field) const
52+
-> std::enable_if_t< !IsPrimitive<T>::value, T >
5153
{
52-
SetStaticField(env, clazz, field, Untag(value));
54+
return T(reinterpret_cast<UntaggedType<T>>(jni::GetStaticField<jobject*>(env, clazz, field)));
55+
}
56+
57+
template < class T >
58+
auto Set(JNIEnv& env, const StaticField<TagType, T>& field, T value) const
59+
-> std::enable_if_t< IsPrimitive<T>::value >
60+
{
61+
SetStaticField<T>(env, clazz, field, value);
62+
}
63+
64+
template < class T >
65+
auto Set(JNIEnv& env, const StaticField<TagType, T>& field, const T& value) const
66+
-> std::enable_if_t< !IsPrimitive<T>::value >
67+
{
68+
SetStaticField<jobject*>(env, clazz, field, value.Get());
69+
}
70+
71+
template < class R, class... Args >
72+
auto Call(JNIEnv& env, const StaticMethod<TagType, R (Args...)>& method, const Args&... args) const
73+
-> std::enable_if_t< IsPrimitive<R>::value, R >
74+
{
75+
return CallStaticMethod<R>(env, clazz, method, Untag(args)...);
5376
}
5477

5578
template < class R, class... Args >
56-
R Call(JNIEnv& env, const StaticMethod<TagType, R (Args...)>& method, const Args&... args) const
79+
auto Call(JNIEnv& env, const StaticMethod<TagType, R (Args...)>& method, const Args&... args) const
80+
-> std::enable_if_t< !IsPrimitive<R>::value, R >
5781
{
58-
return Tag<R>(CallStaticMethod<UntaggedType<R>>(env, clazz, method, Untag(args)...));
82+
return R(reinterpret_cast<UntaggedType<R>>(CallStaticMethod<jobject*>(env, clazz, method, Untag(args)...)));
5983
}
6084

6185
template < class... Args >

include/jni/functions.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,9 @@ namespace jni
260260
}
261261

262262
template < class T >
263-
void SetField(JNIEnv& env, jobject* obj, jfieldID& field, T&& value)
263+
void SetField(JNIEnv& env, jobject* obj, jfieldID& field, T value)
264264
{
265-
(env.*(TypedMethods<T>::SetField))(Unwrap(obj), Unwrap(field), Unwrap(std::forward<T>(value)));
265+
(env.*(TypedMethods<T>::SetField))(Unwrap(obj), Unwrap(field), Unwrap(value));
266266
CheckJavaException(env);
267267
}
268268

@@ -304,9 +304,9 @@ namespace jni
304304
}
305305

306306
template < class T >
307-
void SetStaticField(JNIEnv& env, jclass& clazz, jfieldID& field, T&& value)
307+
void SetStaticField(JNIEnv& env, jclass& clazz, jfieldID& field, T value)
308308
{
309-
(env.*(TypedMethods<T>::SetStaticField))(Unwrap(clazz), Unwrap(field), Unwrap(std::forward<T>(value)));
309+
(env.*(TypedMethods<T>::SetStaticField))(Unwrap(clazz), Unwrap(field), Unwrap(value));
310310
CheckJavaException(env);
311311
}
312312

include/jni/object.hpp

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,45 @@ namespace jni
4949
UntaggedObjectType* Get() const { return obj; }
5050

5151
template < class T >
52-
T Get(JNIEnv& env, const Field<TagType, T>& field) const
52+
auto Get(JNIEnv& env, const Field<TagType, T>& field) const
53+
-> std::enable_if_t< IsPrimitive<T>::value, T >
5354
{
54-
return Tag<T>(GetField<UntaggedType<T>>(env, obj, field));
55+
return GetField<T>(env, obj, field);
5556
}
5657

5758
template < class T >
58-
void Set(JNIEnv& env, const Field<TagType, T>& field, const T& value) const
59+
auto Get(JNIEnv& env, const Field<TagType, T>& field) const
60+
-> std::enable_if_t< !IsPrimitive<T>::value, T >
5961
{
60-
SetField(env, obj, field, Untag(value));
62+
return T(reinterpret_cast<UntaggedType<T>>(GetField<jobject*>(env, obj, field)));
63+
}
64+
65+
template < class T >
66+
auto Set(JNIEnv& env, const Field<TagType, T>& field, T value) const
67+
-> std::enable_if_t< IsPrimitive<T>::value >
68+
{
69+
SetField<T>(env, obj, field, value);
70+
}
71+
72+
template < class T >
73+
auto Set(JNIEnv& env, const Field<TagType, T>& field, const T& value) const
74+
-> std::enable_if_t< !IsPrimitive<T>::value >
75+
{
76+
SetField<jobject*>(env, obj, field, value.Get());
6177
}
6278

6379
template < class R, class... Args >
64-
R Call(JNIEnv& env, const Method<TagType, R (Args...)>& method, const Args&... args) const
80+
auto Call(JNIEnv& env, const Method<TagType, R (Args...)>& method, const Args&... args) const
81+
-> std::enable_if_t< IsPrimitive<R>::value, R >
6582
{
66-
return Tag<R>(CallMethod<UntaggedType<R>>(env, obj, method, Untag(args)...));
83+
return CallMethod<R>(env, obj, method, Untag(args)...);
84+
}
85+
86+
template < class R, class... Args >
87+
auto Call(JNIEnv& env, const Method<TagType, R (Args...)>& method, const Args&... args) const
88+
-> std::enable_if_t< !IsPrimitive<R>::value, R >
89+
{
90+
return R(reinterpret_cast<UntaggedType<R>>(CallMethod<jobject*>(env, obj, method, Untag(args)...)));
6791
}
6892

6993
template < class... Args >
@@ -73,9 +97,17 @@ namespace jni
7397
}
7498

7599
template < class R, class... Args >
76-
R CallNonvirtual(JNIEnv& env, const Class<TagType>& clazz, const Method<TagType, R (Args...)>& method, const Args&... args) const
100+
auto CallNonvirtual(JNIEnv& env, const Class<TagType>& clazz, const Method<TagType, R (Args...)>& method, const Args&... args) const
101+
-> std::enable_if_t< IsPrimitive<R>::value, R >
102+
{
103+
return CallNonvirtualMethod<R>(env, obj, clazz, method, Untag(args)...);
104+
}
105+
106+
template < class R, class... Args >
107+
auto CallNonvirtual(JNIEnv& env, const Class<TagType>& clazz, const Method<TagType, R (Args...)>& method, const Args&... args) const
108+
-> std::enable_if_t< !IsPrimitive<R>::value, R >
77109
{
78-
return Tag<R>(CallNonvirtualMethod<UntaggedType<R>>(env, obj, clazz, method, Untag(args)...));
110+
return R(reinterpret_cast<UntaggedType<R>>(CallNonvirtualMethod<jobject*>(env, obj, clazz, method, Untag(args)...)));
79111
}
80112

81113
template < class... Args >

test/high_level.cpp

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ int main()
4949

5050
static Testable<jni::jclass> classValue;
5151
static Testable<jni::jobject> objectValue;
52+
static Testable<jni::jstring> stringValue;
5253

5354
env.functions->FindClass = [] (JNIEnv*, const char* name) -> jclass
5455
{
@@ -80,6 +81,9 @@ int main()
8081
jni::Object<Test> object { objectValue.Ptr() };
8182
object.NewGlobalRef(env);
8283

84+
jni::String string { stringValue.Ptr() };
85+
string.NewGlobalRef(env);
86+
8387

8488
/// Constructor
8589

@@ -140,8 +144,10 @@ int main()
140144

141145
static Testable<jni::jfieldID> booleanFieldID;
142146
static Testable<jni::jfieldID> objectFieldID;
147+
static Testable<jni::jfieldID> stringFieldID;
143148
static const char * booleanFieldName = "boolean";
144149
static const char * objectFieldName = "object";
150+
static const char * stringFieldName = "string";
145151

146152
env.functions->GetStaticFieldID = [] (JNIEnv*, jclass, const char* name, const char* sig) -> jfieldID
147153
{
@@ -150,11 +156,20 @@ int main()
150156
assert(sig == std::string("Z"));
151157
return jni::Unwrap(booleanFieldID.Ptr());
152158
}
153-
else
159+
else if (name == objectFieldName)
154160
{
155161
assert(sig == std::string("Lmapbox/com/Test;"));
156162
return jni::Unwrap(objectFieldID.Ptr());
157163
}
164+
else if (name == stringFieldName)
165+
{
166+
assert(sig == std::string("Ljava/lang/String;"));
167+
return jni::Unwrap(stringFieldID.Ptr());
168+
}
169+
else
170+
{
171+
abort();
172+
}
158173
};
159174

160175
env.functions->GetStaticBooleanField = [] (JNIEnv*, jclass clazz, jfieldID field) -> jboolean
@@ -208,8 +223,18 @@ int main()
208223
env.functions->GetObjectField = [] (JNIEnv*, jobject obj, jfieldID field) -> jobject
209224
{
210225
assert(obj == jni::Unwrap(objectValue.Ptr()));
211-
assert(field == jni::Unwrap(objectFieldID.Ptr()));
212-
return jni::Unwrap(objectValue.Ptr());
226+
if (field == jni::Unwrap(objectFieldID.Ptr()))
227+
{
228+
return jni::Unwrap(objectValue.Ptr());
229+
}
230+
else if (field == jni::Unwrap(stringFieldID.Ptr()))
231+
{
232+
return jni::Unwrap(stringValue.Ptr());
233+
}
234+
else
235+
{
236+
abort();
237+
}
213238
};
214239

215240
env.functions->SetBooleanField = [] (JNIEnv*, jobject obj, jfieldID field, jboolean value)
@@ -222,16 +247,31 @@ int main()
222247
env.functions->SetObjectField = [] (JNIEnv*, jobject obj, jfieldID field, jobject value)
223248
{
224249
assert(obj == jni::Unwrap(objectValue.Ptr()));
225-
assert(field == jni::Unwrap(objectFieldID.Ptr()));
226-
assert(value == jni::Unwrap(objectValue.Ptr()));
250+
if (field == jni::Unwrap(objectFieldID.Ptr()))
251+
{
252+
assert(value == jni::Unwrap(objectValue.Ptr()));
253+
}
254+
else if (field == jni::Unwrap(stringFieldID.Ptr()))
255+
{
256+
assert(value == jni::Unwrap(stringValue.Ptr()));
257+
}
258+
else
259+
{
260+
abort();
261+
}
227262
};
228263

229264
auto booleanField = testClass.GetField<jni::jboolean>(env, booleanFieldName);
230265
auto objectField = testClass.GetField<jni::Object<Test>>(env, objectFieldName);
266+
auto stringField = testClass.GetField<jni::String>(env, stringFieldName);
267+
231268
assert(object.Get(env, booleanField) == true);
232269
assert(object.Get(env, objectField).Get() == object.Get());
270+
assert(object.Get(env, stringField).Get() == string.Get());
271+
233272
object.Set(env, booleanField, jni::jni_false);
234273
object.Set(env, objectField, object);
274+
object.Set(env, stringField, string);
235275

236276

237277
/// StaticMethod
@@ -616,22 +656,20 @@ int main()
616656

617657
/// Make
618658

619-
static Testable<jni::jstring> stringValue;
620-
621659
env.functions->NewString = [] (JNIEnv*, const jchar*, jsize) -> jstring
622660
{
623661
return jni::Unwrap(stringValue.Ptr());
624662
};
625663

626-
env.functions->GetStringLength = [] (JNIEnv*, jstring string) -> jsize
664+
env.functions->GetStringLength = [] (JNIEnv*, jstring str) -> jsize
627665
{
628-
assert(string == jni::Unwrap(stringValue.Ptr()));
666+
assert(str == jni::Unwrap(stringValue.Ptr()));
629667
return 5;
630668
};
631669

632-
env.functions->GetStringRegion = [] (JNIEnv*, jstring string, jsize start, jsize len, jchar* buf)
670+
env.functions->GetStringRegion = [] (JNIEnv*, jstring str, jsize start, jsize len, jchar* buf)
633671
{
634-
assert(string == jni::Unwrap(stringValue.Ptr()));
672+
assert(str == jni::Unwrap(stringValue.Ptr()));
635673
assert(start == 0);
636674
assert(len == 5);
637675
std::u16string(u"hello").copy(jni::Wrap<char16_t*>(buf), jni::Wrap<std::size_t>(len));

0 commit comments

Comments
 (0)