diff --git a/include/jni/array.hpp b/include/jni/array.hpp index 68a254a..874a9dd 100644 --- a/include/jni/array.hpp +++ b/include/jni/array.hpp @@ -82,11 +82,11 @@ namespace jni }; template < class TheTag > - class Array< Object > + class Array< TypedObject > { public: using TagType = TheTag; - using ElementType = Object; + using ElementType = TypedObject; using UntaggedType = jarray; using UntaggedElementType = typename ElementType::UntaggedObjectType; @@ -124,12 +124,12 @@ namespace jni SetObjectArrayElement(env, SafeDereference(env, array), index, Untag(value)); } - static Array> New(JNIEnv& env, jsize length, const Class& clazz, const Object& initialElement = Object()) + static Array> New(JNIEnv& env, jsize length, const TypedClass& clazz, const TypedObject& initialElement = TypedObject()) { - return Array>(&NewObjectArray(env, length, clazz, initialElement.Get())); + return Array>(&NewObjectArray(env, length, clazz, initialElement.Get())); } - UniqueArray> NewGlobalRef(JNIEnv& env) const + UniqueArray> NewGlobalRef(JNIEnv& env) const { return Seize(env, Array(jni::NewGlobalRef(env, array).release())); } diff --git a/include/jni/class.hpp b/include/jni/class.hpp index 1c087cc..4b9bfd7 100644 --- a/include/jni/class.hpp +++ b/include/jni/class.hpp @@ -1,40 +1,44 @@ #pragma once #include +#include #include #include namespace jni { - template < class TheTag > class Object; - template < class TheTag, class... > class Constructor; - template < class TheTag, class > class Field; - template < class TheTag, class > class StaticField; - template < class TheTag, class > class Method; - template < class TheTag, class > class StaticMethod; + template < class TagType > class TypedObject; + template < class TagType, class... > class TypedConstructor; + template < class TagType, class > class TypedField; + template < class TagType, class > class TypedStaticField; + template < class TagType, class > class TypedMethod; + template < class TagType, class > class TypedStaticMethod; - template < class TheTag > - class Class; + template < class TagType > + class TypedClass; template < class TagType > - class ClassDeleter; + class TypedClassDeleter; template < class TagType > - using UniqueClass = std::unique_ptr< const Class, ClassDeleter >; + using TypedUniqueClass = std::unique_ptr< const TypedClass, TypedClassDeleter >; + + template < class Tag > + using Class = TypedClass< TypeFromTag >; - template < class TheTag > - class Class + template + class TypedClass< Type > { private: jclass* clazz = nullptr; public: - using TagType = TheTag; + using TagType = Type; - explicit Class(std::nullptr_t = nullptr) + explicit TypedClass(std::nullptr_t = nullptr) {} - explicit Class(jclass& c) + explicit TypedClass(jclass& c) : clazz(&c) {} @@ -44,115 +48,116 @@ namespace jni jclass& operator*() const { return *clazz; } jclass* Get() const { return clazz; } - friend bool operator==( const Class& a, const Class& b ) { return a.Get() == b.Get(); } - friend bool operator!=( const Class& a, const Class& b ) { return !( a == b ); } + friend bool operator==( const TypedClass& a, const TypedClass& b ) { return a.Get() == b.Get(); } + friend bool operator!=( const TypedClass& a, const TypedClass& b ) { return !( a == b ); } template < class... Args > - Object New(JNIEnv& env, const Constructor& method, const Args&... args) const + TypedObject New(JNIEnv& env, const TypedConstructor& method, const Args&... args) const { - return Object(&NewObject(env, *clazz, method, Untag(args)...)); + return TypedObject(&NewObject(env, *clazz, method, Untag(args)...)); } template < class T > - auto Get(JNIEnv& env, const StaticField& field) const + auto Get(JNIEnv& env, const TypedStaticField& field) const -> std::enable_if_t< IsPrimitive::value, T > { return jni::GetStaticField(env, *clazz, field); } template < class T > - auto Get(JNIEnv& env, const StaticField& field) const + auto Get(JNIEnv& env, const TypedStaticField& field) const -> std::enable_if_t< !IsPrimitive::value, T > { return T(reinterpret_cast>(jni::GetStaticField(env, *clazz, field))); } template < class T > - auto Set(JNIEnv& env, const StaticField& field, T value) const + auto Set(JNIEnv& env, const TypedStaticField& field, T value) const -> std::enable_if_t< IsPrimitive::value > { SetStaticField(env, *clazz, field, value); } template < class T > - auto Set(JNIEnv& env, const StaticField& field, const T& value) const + auto Set(JNIEnv& env, const TypedStaticField& field, const T& value) const -> std::enable_if_t< !IsPrimitive::value > { SetStaticField(env, *clazz, field, value.Get()); } template < class R, class... Args > - auto Call(JNIEnv& env, const StaticMethod& method, const Args&... args) const + auto Call(JNIEnv& env, const TypedStaticMethod& method, const Args&... args) const -> std::enable_if_t< IsPrimitive::value, R > { return CallStaticMethod(env, *clazz, method, Untag(args)...); } template < class R, class... Args > - auto Call(JNIEnv& env, const StaticMethod& method, const Args&... args) const + auto Call(JNIEnv& env, const TypedStaticMethod& method, const Args&... args) const -> std::enable_if_t< !IsPrimitive::value, R > { return R(reinterpret_cast>(CallStaticMethod(env, *clazz, method, Untag(args)...))); } template < class... Args > - void Call(JNIEnv& env, const StaticMethod& method, const Args&... args) const + void Call(JNIEnv& env, const TypedStaticMethod& method, const Args&... args) const { CallStaticMethod(env, *clazz, method, Untag(args)...); } - static Class Find(JNIEnv& env) + static TypedClass Find(JNIEnv& env) { - return Class(FindClass(env, TagType::Name())); + static constexpr const char name[] { Chars..., '\0' }; + return TypedClass(FindClass(env, name)); } template < class... Args > - Constructor GetConstructor(JNIEnv& env) + TypedConstructor GetConstructor(JNIEnv& env) { - return Constructor(env, *this); + return TypedConstructor(env, *this); } template < class T > - Field GetField(JNIEnv& env, const char* name) + TypedField GetField(JNIEnv& env, const char* name) { - return Field(env, *this, name); + return TypedField(env, *this, name); } template < class T > - StaticField GetStaticField(JNIEnv& env, const char* name) + TypedStaticField GetStaticField(JNIEnv& env, const char* name) { - return StaticField(env, *this, name); + return TypedStaticField(env, *this, name); } template < class T > - Method GetMethod(JNIEnv& env, const char* name) + TypedMethod GetMethod(JNIEnv& env, const char* name) { - return Method(env, *this, name); + return TypedMethod(env, *this, name); } template < class T > - StaticMethod GetStaticMethod(JNIEnv& env, const char* name) + TypedStaticMethod GetStaticMethod(JNIEnv& env, const char* name) { - return StaticMethod(env, *this, name); + return TypedStaticMethod(env, *this, name); } - UniqueClass NewGlobalRef(JNIEnv& env) const + TypedUniqueClass NewGlobalRef(JNIEnv& env) const { - return Seize(env, Class(*jni::NewGlobalRef(env, clazz).release())); + return Seize(env, TypedClass(*jni::NewGlobalRef(env, clazz).release())); } }; - template < class TagType > - class ClassDeleter + template + class TypedClassDeleter< Type > { private: JNIEnv* env = nullptr; public: - using pointer = PointerToValue< Class >; + using pointer = PointerToValue< TypedClass< Type > >; - ClassDeleter() = default; - ClassDeleter(JNIEnv& e) : env(&e) {} + TypedClassDeleter() = default; + TypedClassDeleter(JNIEnv& e) : env(&e) {} void operator()(pointer p) const { @@ -165,8 +170,8 @@ namespace jni }; template < class TagType > - UniqueClass Seize(JNIEnv& env, Class&& clazz) + TypedUniqueClass Seize(JNIEnv& env, TypedClass&& clazz) { - return UniqueClass(PointerToValue>(std::move(clazz)), ClassDeleter(env)); + return TypedUniqueClass(PointerToValue>(std::move(clazz)), TypedClassDeleter(env)); }; } diff --git a/include/jni/constructor.hpp b/include/jni/constructor.hpp index 97896c9..8ad0e09 100644 --- a/include/jni/constructor.hpp +++ b/include/jni/constructor.hpp @@ -4,12 +4,16 @@ namespace jni { + + template < class Tag, class... Args > + using Constructor = TypedConstructor< TypeFromTag, Args... >; + template < class TagType, class... Args > - class Constructor : public Method + class TypedConstructor : public TypedMethod { public: - Constructor(JNIEnv& env, const Class& clazz) - : Method(env, clazz, "") + TypedConstructor(JNIEnv& env, const TypedClass& clazz) + : TypedMethod(env, clazz, "") {} }; } diff --git a/include/jni/field.hpp b/include/jni/field.hpp index 63f5281..19f04e4 100644 --- a/include/jni/field.hpp +++ b/include/jni/field.hpp @@ -8,16 +8,22 @@ namespace jni { - template < class TheTag, class T > - class Field + template < class TagType, class T > + class TypedField; + + template < class Tag, class T > + using Field = TypedField< TypeFromTag, T >; + + template + class TypedField< Type, T > { private: jfieldID& field; public: - using TagType = TheTag; + using TagType = Type; - Field(JNIEnv& env, const Class& clazz, const char* name) + TypedField(JNIEnv& env, const TypedClass& clazz, const char* name) : field(GetFieldID(env, clazz, name, TypeSignature()())) {} diff --git a/include/jni/method.hpp b/include/jni/method.hpp index bbca4ec..b58f607 100644 --- a/include/jni/method.hpp +++ b/include/jni/method.hpp @@ -8,19 +8,22 @@ namespace jni { - template < class TheTag, class > - class Method; + template < class TagType, class > + class TypedMethod; - template < class TheTag, class R, class... Args > - class Method< TheTag, R (Args...) > + template < class Tag, class R, class... Args > + using Method = TypedMethod< TypeFromTag, R (Args...) >; + + template < char... Chars, class R, class... Args > + class TypedMethod< Type, R (Args...) > { private: jmethodID& method; public: - using TagType = TheTag; + using TagType = Type; - Method(JNIEnv& env, const Class& clazz, const char* name) + TypedMethod(JNIEnv& env, const TypedClass& clazz, const char* name) : method(GetMethodID(env, clazz, name, TypeSignature()())) {} diff --git a/include/jni/native_method.hpp b/include/jni/native_method.hpp index 573b8a4..4f2444d 100644 --- a/include/jni/native_method.hpp +++ b/include/jni/native_method.hpp @@ -165,9 +165,9 @@ namespace jni {} template < class Peer, class TagType, class = std::enable_if_t< std::is_same::value > > - auto operator()(const Field& field) + auto operator()(const TypedField& field) { - auto wrapper = [field, lambda = lambda] (JNIEnv& env, Object obj, Args... args) + auto wrapper = [field, lambda = lambda] (JNIEnv& env, TypedObject obj, Args... args) { return lambda(env, *reinterpret_cast(obj.Get(env, field)), std::move(args)...); }; @@ -201,9 +201,9 @@ namespace jni {} template < class Peer, class TagType, class = std::enable_if_t< std::is_same::value > > - auto operator()(const Field& field) + auto operator()(const TypedField& field) { - auto wrapper = [field] (JNIEnv& env, Object obj, Args... args) + auto wrapper = [field] (JNIEnv& env, TypedObject obj, Args... args) { return method(env, *reinterpret_cast(obj.Get(env, field)), std::move(args)...); }; @@ -238,9 +238,9 @@ namespace jni {} template < class Peer, class TagType, class = std::enable_if_t< std::is_same::value > > - auto operator()(const Field& field) + auto operator()(const TypedField& field) { - auto wrapper = [field] (JNIEnv& env, Object obj, Args... args) + auto wrapper = [field] (JNIEnv& env, TypedObject obj, Args... args) { return (reinterpret_cast(obj.Get(env, field))->*method)(env, std::move(args)...); }; @@ -279,9 +279,9 @@ namespace jni */ template < class Peer, class TagType, class... Methods > - void RegisterNativePeer(JNIEnv& env, const Class& clazz, const char* fieldName, Methods&&... methods) + void RegisterNativePeer(JNIEnv& env, const TypedClass& clazz, const char* fieldName, Methods&&... methods) { - static Field field { env, clazz, fieldName }; + static TypedField field { env, clazz, fieldName }; RegisterNatives(env, clazz, methods.template operator()(field)...); } @@ -294,9 +294,9 @@ namespace jni using UniquePeer = std::unique_ptr; using Initializer = UniquePeer (JNIEnv&, Args...); - auto MakeInitializer(const Field& field, const char* name, Initializer* initializer) const + auto MakeInitializer(const TypedField& field, const char* name, Initializer* initializer) const { - auto wrapper = [field, initializer] (JNIEnv& e, Object obj, std::decay_t... args) + auto wrapper = [field, initializer] (JNIEnv& e, TypedObject obj, std::decay_t... args) { UniquePeer previous(reinterpret_cast(obj.Get(e, field))); UniquePeer instance(initializer(e, std::move(args)...)); @@ -307,9 +307,9 @@ namespace jni return MakeNativeMethod(name, wrapper); } - auto MakeFinalizer(const Field& field, const char* name) const + auto MakeFinalizer(const TypedField& field, const char* name) const { - auto wrapper = [field] (JNIEnv& e, Object obj) + auto wrapper = [field] (JNIEnv& e, TypedObject obj) { UniquePeer instance(reinterpret_cast(obj.Get(e, field))); if (instance) obj.Set(e, field, jlong(0)); @@ -321,13 +321,13 @@ namespace jni }; template < class Peer, class TagType, class Initializer, class... Methods > - void RegisterNativePeer(JNIEnv& env, const Class& clazz, const char* fieldName, + void RegisterNativePeer(JNIEnv& env, const TypedClass& clazz, const char* fieldName, Initializer initialize, const char* initializeMethodName, const char* finalizeMethodName, Methods&&... methods) { - static Field field { env, clazz, fieldName }; + static TypedField field { env, clazz, fieldName }; using InitializerMethodType = typename NativeMethodTraits::Type; NativePeerHelper helper; diff --git a/include/jni/object.hpp b/include/jni/object.hpp index 6dd97e8..36bc538 100644 --- a/include/jni/object.hpp +++ b/include/jni/object.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -8,55 +9,70 @@ namespace jni { - template < class TheTag > class Class; - template < class TheTag, class > class Field; - template < class TheTag, class > class Method; + template < class TagType > class TypedClass; + template < class TagType, class > class TypedField; + template < class TagType, class > class TypedMethod; struct ObjectTag { static constexpr auto Name() { return "java/lang/Object"; } }; template < class TagType > - struct UntaggedObjectType { using Type = jobject; }; + struct TypedUntaggedObjectType; - template < class TheTag > - class Object; + template + struct TypedUntaggedObjectType> { using Type = jobject; }; + + template < class TagType = TypeFromTag > + class TypedObject; template < class TagType > - class ObjectDeleter; + class TypedObjectDeleter; + + template < class TagType = TypeFromTag > + using TypedUniqueObject = std::unique_ptr< const TypedObject, TypedObjectDeleter >; - template < class TagType = ObjectTag > - using UniqueObject = std::unique_ptr< const Object, ObjectDeleter >; + template < class Tag = ObjectTag > + using UniqueObject = TypedUniqueObject< TypeFromTag >; template < class TagType > - class WeakObjectRefDeleter; + class TypedWeakObjectRefDeleter; + + template < class TagType = TypeFromTag > + using TypedUniqueWeakObject = std::unique_ptr< const TypedObject, TypedWeakObjectRefDeleter >; - template < class TagType = ObjectTag > - using UniqueWeakObject = std::unique_ptr< const Object, WeakObjectRefDeleter >; + template < class Tag = ObjectTag > + using UniqueWeakObject = TypedUniqueWeakObject< TypeFromTag >; template < class TagType > - class LocalObjectRefDeleter; + class TypedLocalObjectRefDeleter; - template < class TagType = ObjectTag > - using UniqueLocalObject = std::unique_ptr< const Object, LocalObjectRefDeleter >; + template < class TagType = TypeFromTag > + using TypedUniqueLocalObject = std::unique_ptr< const TypedObject, TypedLocalObjectRefDeleter >; - template < class TheTag = ObjectTag > - class Object + template < class Tag = ObjectTag > + using UniqueLocalObject = TypedUniqueLocalObject< TypeFromTag >; + + template < class Tag = ObjectTag > + using Object = TypedObject< TypeFromTag >; + + template < char... Chars > + class TypedObject< Type > { public: - using TagType = TheTag; - using UntaggedObjectType = typename UntaggedObjectType::Type; + using TagType = Type; + using UntaggedObjectType = typename TypedUntaggedObjectType::Type; private: UntaggedObjectType* obj = nullptr; public: - explicit Object(std::nullptr_t = nullptr) + explicit TypedObject(std::nullptr_t = nullptr) {} - explicit Object(UntaggedObjectType* o) + explicit TypedObject(UntaggedObjectType* o) : obj(o) {} - explicit Object(UntaggedObjectType& o) + explicit TypedObject(UntaggedObjectType& o) : obj(&o) {} @@ -66,110 +82,113 @@ namespace jni UntaggedObjectType& operator*() const { return *obj; } UntaggedObjectType* Get() const { return obj; } - friend bool operator==( const Object& a, const Object& b ) { return a.Get() == b.Get(); } - friend bool operator!=( const Object& a, const Object& b ) { return !( a == b ); } + friend bool operator==( const TypedObject& a, const TypedObject& b ) { return a.Get() == b.Get(); } + friend bool operator!=( const TypedObject& a, const TypedObject& b ) { return !( a == b ); } template < class T > - auto Get(JNIEnv& env, const Field& field) const + auto Get(JNIEnv& env, const TypedField& field) const -> std::enable_if_t< IsPrimitive::value, T > { return GetField(env, obj, field); } template < class T > - auto Get(JNIEnv& env, const Field& field) const + auto Get(JNIEnv& env, const TypedField& field) const -> std::enable_if_t< !IsPrimitive::value, T > { return T(reinterpret_cast>(GetField(env, obj, field))); } template < class T > - auto Set(JNIEnv& env, const Field& field, T value) const + auto Set(JNIEnv& env, const TypedField& field, T value) const -> std::enable_if_t< IsPrimitive::value > { SetField(env, obj, field, value); } template < class T > - auto Set(JNIEnv& env, const Field& field, const T& value) const + auto Set(JNIEnv& env, const TypedField& field, const T& value) const -> std::enable_if_t< !IsPrimitive::value > { SetField(env, obj, field, value.Get()); } template < class R, class... Args > - auto Call(JNIEnv& env, const Method& method, const Args&... args) const + auto Call(JNIEnv& env, const TypedMethod& method, const Args&... args) const -> std::enable_if_t< IsPrimitive::value, R > { return CallMethod(env, obj, method, Untag(args)...); } template < class R, class... Args > - auto Call(JNIEnv& env, const Method& method, const Args&... args) const + auto Call(JNIEnv& env, const TypedMethod& method, const Args&... args) const -> std::enable_if_t< !IsPrimitive::value, R > { return R(reinterpret_cast>(CallMethod(env, obj, method, Untag(args)...))); } template < class... Args > - void Call(JNIEnv& env, const Method& method, const Args&... args) const + void Call(JNIEnv& env, const TypedMethod& method, const Args&... args) const { CallMethod(env, obj, method, Untag(args)...); } template < class R, class... Args > - auto CallNonvirtual(JNIEnv& env, const Class& clazz, const Method& method, const Args&... args) const + auto CallNonvirtual(JNIEnv& env, const TypedClass& clazz, const TypedMethod& method, const Args&... args) const -> std::enable_if_t< IsPrimitive::value, R > { return CallNonvirtualMethod(env, obj, clazz, method, Untag(args)...); } template < class R, class... Args > - auto CallNonvirtual(JNIEnv& env, const Class& clazz, const Method& method, const Args&... args) const + auto CallNonvirtual(JNIEnv& env, const TypedClass& clazz, const TypedMethod& method, const Args&... args) const -> std::enable_if_t< !IsPrimitive::value, R > { return R(reinterpret_cast>(CallNonvirtualMethod(env, obj, clazz, method, Untag(args)...))); } template < class... Args > - void CallNonvirtual(JNIEnv& env, const Class& clazz, const Method& method, const Args&... args) const + void CallNonvirtual(JNIEnv& env, const TypedClass& clazz, const TypedMethod& method, const Args&... args) const { CallNonvirtualMethod(env, obj, clazz, method, Untag(args)...); } - UniqueObject NewGlobalRef(JNIEnv& env) const + TypedUniqueObject NewGlobalRef(JNIEnv& env) const { - return Seize(env, Object(jni::NewGlobalRef(env, obj).release())); + return Seize(env, TypedObject(jni::NewGlobalRef(env, obj).release())); } - UniqueWeakObject NewWeakGlobalRef(JNIEnv& env) const + TypedUniqueWeakObject NewWeakGlobalRef(JNIEnv& env) const { - return SeizeWeakRef(env, Object(jni::NewWeakGlobalRef(env, obj).release())); + return SeizeWeakRef(env, TypedObject(jni::NewWeakGlobalRef(env, obj).release())); } - UniqueLocalObject NewLocalRef(JNIEnv& env) const + TypedUniqueLocalObject NewLocalRef(JNIEnv& env) const { - return SeizeLocalRef(env, Object(jni::NewLocalRef(env, obj).release())); + return SeizeLocalRef(env, TypedObject(jni::NewLocalRef(env, obj).release())); } template < class OtherTag > - bool IsInstanceOf(JNIEnv& env, const Class& clazz) const + bool IsInstanceOf(JNIEnv& env, const TypedClass& clazz) const { return jni::IsInstanceOf(env, obj, clazz); } }; - template < class TagType > - class ObjectDeleter + template < class Tag = ObjectTag > + using ObjectDeleter = TypedObjectDeleter< TypeFromTag >; + + template < char... Chars > + class TypedObjectDeleter< Type > { private: JNIEnv* env = nullptr; public: - using pointer = PointerToValue< Object >; + using pointer = PointerToValue< TypedObject< Type > >; - ObjectDeleter() = default; - ObjectDeleter(JNIEnv& e) : env(&e) {} + TypedObjectDeleter() = default; + TypedObjectDeleter(JNIEnv& e) : env(&e) {} void operator()(pointer p) const { @@ -182,22 +201,25 @@ namespace jni }; template < class TagType > - UniqueObject Seize(JNIEnv& env, Object&& object) + TypedUniqueObject Seize(JNIEnv& env, TypedObject&& object) { - return UniqueObject(PointerToValue>(std::move(object)), ObjectDeleter(env)); + return TypedUniqueObject(PointerToValue>(std::move(object)), TypedObjectDeleter(env)); }; - template < class TagType > - class WeakObjectRefDeleter + template < class Tag = ObjectTag > + using WeakObjectRefDeleter = TypedWeakObjectRefDeleter< TypeFromTag >; + + template < char... Chars > + class TypedWeakObjectRefDeleter< Type > { private: JNIEnv* env = nullptr; public: - using pointer = PointerToValue< Object >; + using pointer = PointerToValue< TypedObject< Type > >; - WeakObjectRefDeleter() = default; - WeakObjectRefDeleter(JNIEnv& e) : env(&e) {} + TypedWeakObjectRefDeleter() = default; + TypedWeakObjectRefDeleter(JNIEnv& e) : env(&e) {} void operator()(pointer p) const { @@ -210,22 +232,25 @@ namespace jni }; template < class TagType > - UniqueWeakObject SeizeWeakRef(JNIEnv& env, Object&& object) + TypedUniqueWeakObject SeizeWeakRef(JNIEnv& env, TypedObject&& object) { - return UniqueWeakObject(PointerToValue>(std::move(object)), WeakObjectRefDeleter(env)); + return TypedUniqueWeakObject(PointerToValue>(std::move(object)), TypedWeakObjectRefDeleter(env)); }; - template < class TagType > - class LocalObjectRefDeleter + template < class Tag = ObjectTag > + using LocalObjectRefDeleter = TypedLocalObjectRefDeleter< TypeFromTag >; + + template < char... Chars > + class TypedLocalObjectRefDeleter< Type > { private: JNIEnv* env = nullptr; public: - using pointer = PointerToValue< Object >; + using pointer = PointerToValue< TypedObject< Type > >; - LocalObjectRefDeleter() = default; - LocalObjectRefDeleter(JNIEnv& e) : env(&e) {} + TypedLocalObjectRefDeleter() = default; + TypedLocalObjectRefDeleter(JNIEnv& e) : env(&e) {} void operator()(pointer p) const { @@ -238,14 +263,14 @@ namespace jni }; template < class TagType > - UniqueLocalObject SeizeLocalRef(JNIEnv& env, Object&& object) + TypedUniqueLocalObject SeizeLocalRef(JNIEnv& env, TypedObject&& object) { - return UniqueLocalObject(PointerToValue>(std::move(object)), LocalObjectRefDeleter(env)); + return TypedUniqueLocalObject(PointerToValue>(std::move(object)), TypedLocalObjectRefDeleter(env)); }; template < class OutTagType, class InTagType > - Object Cast(JNIEnv& env, const Object& object, const Class& clazz) + TypedObject Cast(JNIEnv& env, const TypedObject& object, const TypedClass& clazz) { if (!object.IsInstanceOf(env, clazz)) { diff --git a/include/jni/static_field.hpp b/include/jni/static_field.hpp index 42c2944..8a499c4 100644 --- a/include/jni/static_field.hpp +++ b/include/jni/static_field.hpp @@ -8,16 +8,22 @@ namespace jni { - template < class TheTag, class T > - class StaticField + template < class TagType, class T > + class TypedStaticField; + + template < class Tag, class T > + using StaticField = TypedStaticField< TypeFromTag, T >; + + template + class TypedStaticField< Type, T > { private: jfieldID& field; public: - using TagType = TheTag; + using TagType = Type; - StaticField(JNIEnv& env, const Class& clazz, const char* name) + TypedStaticField(JNIEnv& env, const TypedClass& clazz, const char* name) : field(GetStaticFieldID(env, clazz, name, TypeSignature()())) {} diff --git a/include/jni/static_method.hpp b/include/jni/static_method.hpp index 9b28cce..29cf7e9 100644 --- a/include/jni/static_method.hpp +++ b/include/jni/static_method.hpp @@ -8,19 +8,22 @@ namespace jni { - template < class TheTag, class > - class StaticMethod; + template < class TagType, class > + class TypedStaticMethod; - template < class TheTag, class R, class... Args > - class StaticMethod< TheTag, R (Args...) > + template < class Tag, class R, class... Args > + using StaticMethod = TypedStaticMethod< TypeFromTag, R (Args...) >; + + template + class TypedStaticMethod< Type, R (Args...) > { private: jmethodID& method; public: - using TagType = TheTag; + using TagType = Type; - StaticMethod(JNIEnv& env, const Class& clazz, const char* name) + TypedStaticMethod(JNIEnv& env, const TypedClass& clazz, const char* name) : method(GetStaticMethodID(env, clazz, name, TypeSignature()())) {} diff --git a/include/jni/string.hpp b/include/jni/string.hpp index 0e5b00c..bac05b7 100644 --- a/include/jni/string.hpp +++ b/include/jni/string.hpp @@ -13,7 +13,7 @@ namespace jni struct StringTag { static constexpr auto Name() { return "java/lang/String"; } }; template <> - struct UntaggedObjectType { using Type = jstring; }; + struct TypedUntaggedObjectType< TypeFromTag > { using Type = jstring; }; using String = Object; diff --git a/include/jni/type.hpp b/include/jni/type.hpp new file mode 100644 index 0000000..b26e45d --- /dev/null +++ b/include/jni/type.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include + +namespace jni + { + template < char... Chars > struct Type {}; + + template < class Tag > + struct TypeFactory { + private: + static constexpr std::size_t Size(char const* str, std::size_t count = 0) { + return (str[0] == '\0') ? count : Size(str + 1, count + 1); + } + + template + static Type ExpandType(std::index_sequence); + + public: + using TagType = decltype(ExpandType(std::make_index_sequence{})); + }; + + template < class Tag > + using TypeFromTag = typename TypeFactory::TagType; + } diff --git a/include/jni/type_signature.hpp b/include/jni/type_signature.hpp index 090b95d..a22281f 100644 --- a/include/jni/type_signature.hpp +++ b/include/jni/type_signature.hpp @@ -21,13 +21,13 @@ namespace jni template <> struct TypeSignature< jdouble > { const char * operator()() const { return "D"; } }; template <> struct TypeSignature< void > { const char * operator()() const { return "V"; } }; - template < class TheTag > - struct TypeSignature< Object > + template < char... Chars > + struct TypeSignature< TypedObject< Type > > { const char * operator()() const { - static std::string value { std::string("L") + TheTag::Name() + ";" }; - return value.c_str(); + static constexpr const char value[] = { 'L', Chars..., ';', '\0' }; + return value; } }; diff --git a/test/high_level.cpp b/test/high_level.cpp index 9dc2d10..a1de6de 100644 --- a/test/high_level.cpp +++ b/test/high_level.cpp @@ -63,7 +63,7 @@ int main() env.functions->FindClass = [] (JNIEnv*, const char* name) -> jclass { - assert(name == Test::Name()); + assert(strcmp(name, Test::Name()) == 0); return Unwrap(classValue.Ptr()); };