19 #include "djinni_support.hpp" 24 #include <unordered_map> 25 #include <unordered_set> 30 template<
class Self,
class CppT,
class JniT>
37 static CppType toCpp(JNIEnv* , JniType j) noexcept {
return static_cast<CppType
>(j); }
38 static JniType fromCpp(JNIEnv* , CppType c) noexcept {
return static_cast<JniType
>(c); }
42 using JniType = jobject;
43 static CppType toCpp(JNIEnv* jniEnv, JniType j)
47 assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
48 auto ret = Primitive::toCpp(jniEnv, Self::unbox(jniEnv, data.method_unbox, j));
49 jniExceptionCheck(jniEnv);
55 auto ret = jniEnv->CallStaticObjectMethod(data.clazz.get(), data.method_box, Primitive::fromCpp(jniEnv, c));
56 jniExceptionCheck(jniEnv);
63 const char* staticBoxMethod,
64 const char* staticBoxMethodSignature,
65 const char* unboxMethod,
66 const char* unboxMethodSignature)
67 : clazz(jniFindClass(javaClassSpec))
68 , method_box(jniGetStaticMethodID(clazz.get(), staticBoxMethod, staticBoxMethodSignature))
69 , method_unbox(jniGetMethodID(clazz.get(), unboxMethod, unboxMethodSignature))
74 const jmethodID method_box;
75 const jmethodID method_unbox;
80 Bool() :
Primitive(
"java/lang/Boolean",
"valueOf",
"(Z)Ljava/lang/Boolean;",
"booleanValue",
"()Z") {}
83 static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) {
84 auto result = jniEnv->CallBooleanMethod(j, method);
85 jniExceptionCheck(jniEnv);
92 I8() :
Primitive(
"java/lang/Byte",
"valueOf",
"(B)Ljava/lang/Byte;",
"byteValue",
"()B") {}
95 static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) {
96 auto result = jniEnv->CallByteMethod(j, method);
97 jniExceptionCheck(jniEnv);
104 I16() :
Primitive(
"java/lang/Short",
"valueOf",
"(S)Ljava/lang/Short;",
"shortValue",
"()S") {}
107 static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) {
108 auto result = jniEnv->CallShortMethod(j, method);
109 jniExceptionCheck(jniEnv);
116 I32() :
Primitive(
"java/lang/Integer",
"valueOf",
"(I)Ljava/lang/Integer;",
"intValue",
"()I") {}
119 static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) {
120 auto result = jniEnv->CallIntMethod(j, method);
121 jniExceptionCheck(jniEnv);
128 I64() :
Primitive(
"java/lang/Long",
"valueOf",
"(J)Ljava/lang/Long;",
"longValue",
"()J") {}
131 static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) {
132 auto result = jniEnv->CallLongMethod(j, method);
133 jniExceptionCheck(jniEnv);
140 F32() :
Primitive(
"java/lang/Float",
"valueOf",
"(F)Ljava/lang/Float;",
"floatValue",
"()F") {}
143 static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) {
144 auto result = jniEnv->CallFloatMethod(j, method);
145 jniExceptionCheck(jniEnv);
152 F64() :
Primitive(
"java/lang/Double",
"valueOf",
"(D)Ljava/lang/Double;",
"doubleValue",
"()D") {}
155 static JniType unbox(JNIEnv* jniEnv, jmethodID method, jobject j) {
156 auto result = jniEnv->CallDoubleMethod(j, method);
157 jniExceptionCheck(jniEnv);
164 using CppType = std::string;
165 using JniType = jstring;
169 static CppType toCpp(JNIEnv* jniEnv, JniType j)
171 assert(j !=
nullptr);
172 return jniUTF8FromString(jniEnv, j);
177 return {jniEnv, jniStringFromUTF8(jniEnv, c)};
183 using CppType = std::wstring;
184 using JniType = jstring;
188 static CppType toCpp(JNIEnv* jniEnv, JniType j)
190 assert(j !=
nullptr);
191 return jniWStringFromString(jniEnv, j);
196 return {jniEnv, jniStringFromWString(jniEnv, c)};
202 using CppType = std::vector<uint8_t>;
203 using JniType = jbyteArray;
207 static CppType toCpp(JNIEnv* jniEnv, JniType j)
209 assert(j !=
nullptr);
211 std::vector<uint8_t> ret;
212 jsize length = jniEnv->GetArrayLength(j);
213 jniExceptionCheck(jniEnv);
220 auto deleter = [jniEnv, j] (
void* c) {
222 jniEnv->ReleasePrimitiveArrayCritical(j, c, JNI_ABORT);
226 std::unique_ptr<uint8_t, decltype(deleter)> ptr(
227 reinterpret_cast<uint8_t*>(jniEnv->GetPrimitiveArrayCritical(j,
nullptr)),
234 ret = std::vector<uint8_t>{ptr.get(), ptr.get() + length};
237 jniExceptionCheck(jniEnv);
246 assert(c.size() <= std::numeric_limits<jsize>::max());
248 jniExceptionCheck(jniEnv);
252 jniEnv->SetByteArrayRegion(j.get(), 0, jsize(c.size()), reinterpret_cast<const jbyte*>(c.data()));
260 using CppType = std::chrono::system_clock::time_point;
261 using JniType = jobject;
265 static CppType toCpp(JNIEnv* jniEnv, JniType j)
267 static const auto POSIX_EPOCH = std::chrono::system_clock::from_time_t(0);
268 assert(j !=
nullptr);
270 assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
271 auto time_millis = jniEnv->CallLongMethod(j, data.method_get_time);
272 jniExceptionCheck(jniEnv);
273 return POSIX_EPOCH + std::chrono::milliseconds{time_millis};
278 static const auto POSIX_EPOCH = std::chrono::system_clock::from_time_t(0);
280 const auto cpp_millis = std::chrono::duration_cast<std::chrono::milliseconds>(c - POSIX_EPOCH);
281 const jlong millis =
static_cast<jlong
>(cpp_millis.count());
282 auto j =
LocalRef<jobject>(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor, millis));
283 jniExceptionCheck(jniEnv);
289 friend ::djinni::JniClass<Date>;
292 const jmethodID constructor { jniGetMethodID(clazz.get(),
"<init>",
"(J)V") };
293 const jmethodID method_get_time { jniGetMethodID(clazz.get(),
"getTime",
"()J") };
296 template <
template <
class>
class OptionalType,
class T>
303 template <
typename C>
static OptionalType<typename C::CppType> opt_type(...);
304 template <
typename C>
static typename C::CppOptType opt_type(
typename C::CppOptType *);
305 using CppType = decltype(opt_type<T>(
nullptr));
307 using JniType =
typename T::Boxed::JniType;
311 static CppType toCpp(JNIEnv* jniEnv, JniType j)
314 return T::Boxed::toCpp(jniEnv, j);
320 static LocalRef<JniType> fromCpp(JNIEnv* jniEnv,
const OptionalType<typename T::CppType> &c)
326 template <
typename C = T>
327 static LocalRef<JniType> fromCpp(JNIEnv* jniEnv,
const typename C::CppOptType & cppOpt) {
328 return T::Boxed::fromCppOpt(jniEnv, cppOpt);
335 const jmethodID constructor { jniGetMethodID(clazz.get(),
"<init>",
"(I)V") };
336 const jmethodID method_add { jniGetMethodID(clazz.get(),
"add",
"(Ljava/lang/Object;)Z") };
337 const jmethodID method_get { jniGetMethodID(clazz.get(),
"get",
"(I)Ljava/lang/Object;") };
338 const jmethodID method_size { jniGetMethodID(clazz.get(),
"size",
"()I") };
344 using ECppType =
typename T::CppType;
345 using EJniType =
typename T::Boxed::JniType;
348 using CppType = std::vector<ECppType>;
349 using JniType = jobject;
353 static CppType toCpp(JNIEnv* jniEnv, JniType j)
355 assert(j !=
nullptr);
357 assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
358 auto size = jniEnv->CallIntMethod(j, data.method_size);
359 jniExceptionCheck(jniEnv);
362 for(jint i = 0; i < size; ++i)
364 auto je =
LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(j, data.method_get, i));
365 jniExceptionCheck(jniEnv);
366 c.push_back(T::Boxed::toCpp(jniEnv, static_cast<EJniType>(je.get())));
374 assert(c.size() <= std::numeric_limits<jint>::max());
375 auto size =
static_cast<jint
>(c.size());
376 auto j =
LocalRef<jobject>(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor, size));
377 jniExceptionCheck(jniEnv);
378 for(
const auto& ce : c)
380 auto je = T::Boxed::fromCpp(jniEnv, ce);
381 jniEnv->CallBooleanMethod(j, data.method_add,
get(je));
382 jniExceptionCheck(jniEnv);
391 const jmethodID method_next { jniGetMethodID(clazz.get(),
"next",
"()Ljava/lang/Object;") };
397 const jmethodID constructor { jniGetMethodID(clazz.get(),
"<init>",
"()V") };
398 const jmethodID method_add { jniGetMethodID(clazz.get(),
"add",
"(Ljava/lang/Object;)Z") };
399 const jmethodID method_size { jniGetMethodID(clazz.get(),
"size",
"()I") };
400 const jmethodID method_iterator { jniGetMethodID(clazz.get(),
"iterator",
"()Ljava/util/Iterator;") };
406 using ECppType =
typename T::CppType;
407 using EJniType =
typename T::Boxed::JniType;
410 using CppType = std::unordered_set<ECppType>;
411 using JniType = jobject;
415 static CppType toCpp(JNIEnv* jniEnv, JniType j)
417 assert(j !=
nullptr);
420 assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
421 auto size = jniEnv->CallIntMethod(j, data.method_size);
422 jniExceptionCheck(jniEnv);
424 auto it =
LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(j, data.method_iterator));
425 jniExceptionCheck(jniEnv);
426 for(jint i = 0; i < size; ++i)
428 auto je =
LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(it, iteData.method_next));
429 jniExceptionCheck(jniEnv);
430 c.insert(T::Boxed::toCpp(jniEnv, static_cast<EJniType>(je.get())));
438 assert(c.size() <= std::numeric_limits<jint>::max());
439 auto size =
static_cast<jint
>(c.size());
440 auto j =
LocalRef<jobject>(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor, size));
441 jniExceptionCheck(jniEnv);
442 for(
const auto& ce : c)
444 auto je = T::Boxed::fromCpp(jniEnv, ce);
445 jniEnv->CallBooleanMethod(j, data.method_add,
get(je));
446 jniExceptionCheck(jniEnv);
455 const jmethodID constructor { jniGetMethodID(clazz.get(),
"<init>",
"()V") };
456 const jmethodID method_put { jniGetMethodID(clazz.get(),
"put",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") };
457 const jmethodID method_size { jniGetMethodID(clazz.get(),
"size",
"()I") };
458 const jmethodID method_entrySet { jniGetMethodID(clazz.get(),
"entrySet",
"()Ljava/util/Set;") };
464 const jmethodID method_iterator { jniGetMethodID(clazz.get(),
"iterator",
"()Ljava/util/Iterator;") };
470 const jmethodID method_getKey { jniGetMethodID(clazz.get(),
"getKey",
"()Ljava/lang/Object;") };
471 const jmethodID method_getValue { jniGetMethodID(clazz.get(),
"getValue",
"()Ljava/lang/Object;") };
474 template <
class Key,
class Value>
477 using CppKeyType =
typename Key::CppType;
478 using CppValueType =
typename Value::CppType;
479 using JniKeyType =
typename Key::Boxed::JniType;
480 using JniValueType =
typename Value::Boxed::JniType;
483 using CppType = std::unordered_map<CppKeyType, CppValueType>;
484 using JniType = jobject;
488 static CppType toCpp(JNIEnv* jniEnv, JniType j)
490 assert(j !=
nullptr);
495 assert(jniEnv->IsInstanceOf(j, data.clazz.get()));
496 auto size = jniEnv->CallIntMethod(j, data.method_size);
497 jniExceptionCheck(jniEnv);
498 auto entrySet =
LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(j, data.method_entrySet));
499 jniExceptionCheck(jniEnv);
502 auto it =
LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(entrySet, entrySetData.method_iterator));
503 jniExceptionCheck(jniEnv);
504 for(jint i = 0; i < size; ++i)
506 auto je =
LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(it, iteData.method_next));
507 jniExceptionCheck(jniEnv);
508 auto jKey =
LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(je, entryData.method_getKey));
509 jniExceptionCheck(jniEnv);
510 auto jValue =
LocalRef<jobject>(jniEnv, jniEnv->CallObjectMethod(je, entryData.method_getValue));
511 jniExceptionCheck(jniEnv);
512 c.emplace(Key::Boxed::toCpp(jniEnv, static_cast<JniKeyType>(jKey.get())),
513 Value::Boxed::toCpp(jniEnv, static_cast<JniValueType>(jValue.get())));
521 assert(c.size() <= std::numeric_limits<jint>::max());
522 auto size = c.size();
523 auto j =
LocalRef<jobject>(jniEnv, jniEnv->NewObject(data.clazz.get(), data.constructor, size));
524 jniExceptionCheck(jniEnv);
525 for(
const auto& ce : c)
527 auto jKey = Key::Boxed::fromCpp(jniEnv, ce.first);
528 auto jValue = Value::Boxed::fromCpp(jniEnv, ce.second);
529 jniEnv->CallObjectMethod(j, data.method_put,
get(jKey),
get(jValue));
530 jniExceptionCheck(jniEnv);
Definition: Marshal.hpp:452
Definition: Marshal.hpp:181
Definition: Marshal.hpp:297
Definition: Marshal.hpp:102
Definition: Marshal.hpp:467
Definition: djinni_support.hpp:80
Definition: Marshal.hpp:342
Definition: Marshal.hpp:200
Definition: Marshal.hpp:40
Definition: Marshal.hpp:90
Definition: Marshal.hpp:332
Definition: Marshal.hpp:404
Definition: Marshal.hpp:475
Definition: Marshal.hpp:78
Definition: Marshal.hpp:114
Definition: Marshal.hpp:138
Definition: djinni_support.cpp:27
Definition: Marshal.hpp:258
Definition: djinni_support.hpp:223
Definition: Marshal.hpp:126
Definition: Marshal.hpp:150
Definition: Marshal.hpp:394
Definition: Marshal.hpp:388
Definition: Marshal.hpp:162
Definition: Marshal.hpp:31
Definition: Marshal.hpp:461