#pragma once #include #include #include #include #include #include namespace jni { template < class W > struct Wrapper; template < class W, class U > auto Wrap(U&& u) { return Wrapper().Wrap(std::forward(u)); } template < class W > auto Unwrap(W&& w) { return Wrapper::type>().Unwrap(std::forward(w)); } template < class T > using UnwrappedType = decltype(Unwrap(std::declval())); template < class T > struct PrimitiveTypeWrapper { T Wrap(T t) const { return t; } T Unwrap(T t) const { return t; } }; template <> struct Wrapper< jboolean > : PrimitiveTypeWrapper< jboolean > {}; template <> struct Wrapper< jbyte > : PrimitiveTypeWrapper< jbyte > {}; template <> struct Wrapper< jchar > : PrimitiveTypeWrapper< jchar > {}; template <> struct Wrapper< jshort > : PrimitiveTypeWrapper< jshort > {}; template <> struct Wrapper< jint > : PrimitiveTypeWrapper< jint > {}; template <> struct Wrapper< jlong > : PrimitiveTypeWrapper< jlong > {}; template <> struct Wrapper< jfloat > : PrimitiveTypeWrapper< jfloat > {}; template <> struct Wrapper< jdouble > : PrimitiveTypeWrapper< jdouble > {}; template <> struct Wrapper { const char16_t* Wrap(const jchar* s) const { return reinterpret_cast(s); } const jchar* Unwrap(const char16_t* s) const { return reinterpret_cast(s); } }; template <> struct Wrapper { char16_t* Wrap(jchar* s) const { return reinterpret_cast(s); } jchar* Unwrap(char16_t* s) const { return reinterpret_cast(s); } }; template <> struct Wrapper { jsize Wrap(::jsize s) const { if (s < 0) throw std::range_error("::jsize < 0"); return static_cast(s); } ::jsize Unwrap(jsize s) const { if (s > std::numeric_limits<::jsize>::max()) throw std::range_error("jsize > max"); return static_cast<::jsize>(s); } }; template < class W, class U > struct ReferenceTypeWrapper { W* Wrap(U u) const { return reinterpret_cast(u); } U Unwrap(W* w) const { return reinterpret_cast(w); } }; template <> struct Wrapper< jobject* > : ReferenceTypeWrapper< jobject, ::jobject > {}; template <> struct Wrapper< jclass* > : ReferenceTypeWrapper< jclass, ::jclass > {}; template <> struct Wrapper< jstring* > : ReferenceTypeWrapper< jstring, ::jstring > {}; template <> struct Wrapper< jthrowable* > : ReferenceTypeWrapper< jthrowable, ::jthrowable > {}; template <> struct Wrapper< jarray< jobject >* > : ReferenceTypeWrapper< jarray< jobject >, ::jobjectArray > {}; template <> struct Wrapper< jarray< jboolean >* > : ReferenceTypeWrapper< jarray< jboolean >, ::jbooleanArray > {}; template <> struct Wrapper< jarray< jbyte >* > : ReferenceTypeWrapper< jarray< jbyte >, ::jbyteArray > {}; template <> struct Wrapper< jarray< jchar >* > : ReferenceTypeWrapper< jarray< jchar >, ::jcharArray > {}; template <> struct Wrapper< jarray< jshort >* > : ReferenceTypeWrapper< jarray< jshort >, ::jshortArray > {}; template <> struct Wrapper< jarray< jint >* > : ReferenceTypeWrapper< jarray< jint >, ::jintArray > {}; template <> struct Wrapper< jarray< jlong >* > : ReferenceTypeWrapper< jarray< jlong >, ::jlongArray > {}; template <> struct Wrapper< jarray< jfloat >* > : ReferenceTypeWrapper< jarray< jfloat >, ::jfloatArray > {}; template <> struct Wrapper< jarray< jdouble >* > : ReferenceTypeWrapper< jarray< jdouble >, ::jdoubleArray > {}; template <> struct Wrapper< jfieldID* > : ReferenceTypeWrapper< jfieldID, ::jfieldID > {}; template <> struct Wrapper< jmethodID* > : ReferenceTypeWrapper< jmethodID, ::jmethodID > {}; // Allow references to be unwrapped to pointers to the underlying type, but not the // reverse, because dereferences should be explicit, with null checks where necessary. template < class W, class U > struct ReferenceTypeUnwrapper { U Unwrap(W& w) const { return reinterpret_cast(&w); } }; template <> struct Wrapper< jobject > : ReferenceTypeUnwrapper< jobject, ::jobject > {}; template <> struct Wrapper< jclass > : ReferenceTypeUnwrapper< jclass, ::jclass > {}; template <> struct Wrapper< jstring > : ReferenceTypeUnwrapper< jstring, ::jstring > {}; template <> struct Wrapper< jthrowable > : ReferenceTypeUnwrapper< jthrowable, ::jthrowable > {}; template <> struct Wrapper< jarray< jobject > > : ReferenceTypeUnwrapper< jarray< jobject >, ::jobjectArray > {}; template <> struct Wrapper< jarray< jboolean > > : ReferenceTypeUnwrapper< jarray< jboolean >, ::jbooleanArray > {}; template <> struct Wrapper< jarray< jbyte > > : ReferenceTypeUnwrapper< jarray< jbyte >, ::jbyteArray > {}; template <> struct Wrapper< jarray< jchar > > : ReferenceTypeUnwrapper< jarray< jchar >, ::jcharArray > {}; template <> struct Wrapper< jarray< jshort > > : ReferenceTypeUnwrapper< jarray< jshort >, ::jshortArray > {}; template <> struct Wrapper< jarray< jint > > : ReferenceTypeUnwrapper< jarray< jint >, ::jintArray > {}; template <> struct Wrapper< jarray< jlong > > : ReferenceTypeUnwrapper< jarray< jlong >, ::jlongArray > {}; template <> struct Wrapper< jarray< jfloat > > : ReferenceTypeUnwrapper< jarray< jfloat >, ::jfloatArray > {}; template <> struct Wrapper< jarray< jdouble > > : ReferenceTypeUnwrapper< jarray< jdouble >, ::jdoubleArray > {}; template <> struct Wrapper< jfieldID > : ReferenceTypeUnwrapper< jfieldID, ::jfieldID > {}; template <> struct Wrapper< jmethodID > : ReferenceTypeUnwrapper< jmethodID, ::jmethodID > {}; template < class T, class R, class... Args > struct Wrapper< JNINativeMethod< R (JNIEnv*, T*, Args...) > > { ::JNINativeMethod Unwrap(JNINativeMethod method) const { return { const_cast(method.name), const_cast(method.signature), reinterpret_cast(method.fnPtr) }; } }; template <> struct Wrapper { version Wrap(::jint v) const { return static_cast(v); } ::jint Unwrap(version v) const { return static_cast<::jint>(v); } }; }