mirror of https://github.com/axmolengine/axmol.git
154 lines
6.7 KiB
C++
154 lines
6.7 KiB
C++
|
#pragma once
|
||
|
|
||
|
#include <jni/functions.hpp>
|
||
|
#include <jni/tagging.hpp>
|
||
|
|
||
|
#include <cstddef>
|
||
|
|
||
|
namespace jni
|
||
|
{
|
||
|
template < class TheTag > class Class;
|
||
|
template < class TheTag, class > class Field;
|
||
|
template < class TheTag, class > class Method;
|
||
|
|
||
|
class ObjectBase
|
||
|
{
|
||
|
protected:
|
||
|
jobject* ptr = nullptr;
|
||
|
|
||
|
explicit ObjectBase(std::nullptr_t = nullptr)
|
||
|
{}
|
||
|
|
||
|
explicit ObjectBase(jobject* p)
|
||
|
: ptr(p)
|
||
|
{}
|
||
|
|
||
|
~ObjectBase() = default;
|
||
|
|
||
|
void reset(jobject* p) { ptr = p; }
|
||
|
|
||
|
public:
|
||
|
explicit operator bool() const { return ptr; }
|
||
|
|
||
|
friend bool operator==(const ObjectBase& a, const ObjectBase& b) { return a.ptr == b.ptr; }
|
||
|
friend bool operator!=(const ObjectBase& a, const ObjectBase& b) { return !( a == b ); }
|
||
|
|
||
|
template < class OtherTag >
|
||
|
bool IsInstanceOf(JNIEnv& env, const Class<OtherTag>& clazz) const
|
||
|
{
|
||
|
return jni::IsInstanceOf(env, ptr, *clazz);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template < class TheTag = ObjectTag >
|
||
|
class Object : public TagTraits<TheTag>::SuperType
|
||
|
{
|
||
|
public:
|
||
|
using TagType = TheTag;
|
||
|
using SuperType = typename TagTraits<TheTag>::SuperType;
|
||
|
using UntaggedType = typename TagTraits<TheTag>::UntaggedType;
|
||
|
|
||
|
explicit Object(UntaggedType* p)
|
||
|
: SuperType(p)
|
||
|
{}
|
||
|
|
||
|
protected:
|
||
|
explicit Object(std::nullptr_t = nullptr)
|
||
|
{}
|
||
|
|
||
|
Object(const Object&) = delete;
|
||
|
Object& operator=(const Object&) = delete;
|
||
|
|
||
|
public:
|
||
|
UntaggedType* get() const { return reinterpret_cast<UntaggedType*>(this->ptr); }
|
||
|
UntaggedType& operator*() const { return *get(); }
|
||
|
|
||
|
template < class T >
|
||
|
auto Get(JNIEnv& env, const Field<TagType, T>& field) const
|
||
|
-> std::enable_if_t< IsPrimitive<T>::value, T >
|
||
|
{
|
||
|
return GetField<T>(env, get(), field);
|
||
|
}
|
||
|
|
||
|
template < class T >
|
||
|
auto Get(JNIEnv& env, const Field<TagType, T>& field) const
|
||
|
-> std::enable_if_t< !IsPrimitive<T>::value, Local<T> >
|
||
|
{
|
||
|
return Local<T>(env, reinterpret_cast<typename T::UntaggedType*>(GetField<jobject*>(env, get(), field)));
|
||
|
}
|
||
|
|
||
|
template < class T >
|
||
|
auto Set(JNIEnv& env, const Field<TagType, T>& field, T value) const
|
||
|
-> std::enable_if_t< IsPrimitive<T>::value >
|
||
|
{
|
||
|
SetField<T>(env, get(), field, value);
|
||
|
}
|
||
|
|
||
|
template < class Expected, class Actual >
|
||
|
auto Set(JNIEnv& env, const Field<TagType, Expected>& field, const Actual& value) const
|
||
|
-> std::enable_if_t< !IsPrimitive<Expected>::value
|
||
|
&& std::is_convertible<const Actual&, const Expected&>::value >
|
||
|
{
|
||
|
SetField<jobject*>(env, get(), field, value.get());
|
||
|
}
|
||
|
|
||
|
template < class R, class... ExpectedArgs, class... ActualArgs >
|
||
|
auto Call(JNIEnv& env, const Method<TagType, R (ExpectedArgs...)>& method, const ActualArgs&... args) const
|
||
|
-> std::enable_if_t< IsPrimitive<R>::value
|
||
|
&& Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value, R >
|
||
|
{
|
||
|
return CallMethod<R>(env, get(), method, Untag(args)...);
|
||
|
}
|
||
|
|
||
|
template < class R, class... ExpectedArgs, class... ActualArgs >
|
||
|
auto Call(JNIEnv& env, const Method<TagType, R (ExpectedArgs...)>& method, const ActualArgs&... args) const
|
||
|
-> std::enable_if_t< !IsPrimitive<R>::value
|
||
|
&& !std::is_void<R>::value
|
||
|
&& Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value, Local<R> >
|
||
|
{
|
||
|
return Local<R>(env, reinterpret_cast<typename R::UntaggedType*>(CallMethod<jobject*>(env, get(), method, Untag(args)...)));
|
||
|
}
|
||
|
|
||
|
template < class... ExpectedArgs, class... ActualArgs >
|
||
|
auto Call(JNIEnv& env, const Method<TagType, void (ExpectedArgs...)>& method, const ActualArgs&... args) const
|
||
|
-> std::enable_if_t< Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value >
|
||
|
{
|
||
|
CallMethod<void>(env, get(), method, Untag(args)...);
|
||
|
}
|
||
|
|
||
|
template < class R, class... ExpectedArgs, class... ActualArgs >
|
||
|
auto CallNonvirtual(JNIEnv& env, const Class<TagType>& clazz, const Method<TagType, R (ExpectedArgs...)>& method, const ActualArgs&... args) const
|
||
|
-> std::enable_if_t< IsPrimitive<R>::value
|
||
|
&& Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value, R >
|
||
|
{
|
||
|
return CallNonvirtualMethod<R>(env, get(), clazz, method, Untag(args)...);
|
||
|
}
|
||
|
|
||
|
template < class R, class... ExpectedArgs, class... ActualArgs >
|
||
|
auto CallNonvirtual(JNIEnv& env, const Class<TagType>& clazz, const Method<TagType, R (ExpectedArgs...)>& method, const ActualArgs&... args) const
|
||
|
-> std::enable_if_t< !IsPrimitive<R>::value
|
||
|
&& !std::is_void<R>::value
|
||
|
&& Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value, Local<R> >
|
||
|
{
|
||
|
return Local<R>(env, reinterpret_cast<typename R::UntaggedType*>(CallNonvirtualMethod<jobject*>(env, get(), clazz, method, Untag(args)...)));
|
||
|
}
|
||
|
|
||
|
template < class... ExpectedArgs, class... ActualArgs >
|
||
|
auto CallNonvirtual(JNIEnv& env, const Class<TagType>& clazz, const Method<TagType, void (ExpectedArgs...)>& method, const ActualArgs&... args) const
|
||
|
-> std::enable_if_t< Conjunction<std::is_convertible<const ActualArgs&, const ExpectedArgs&>...>::value >
|
||
|
{
|
||
|
CallNonvirtualMethod<void>(env, get(), clazz, method, Untag(args)...);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template < class OutTagType, class T >
|
||
|
Local<Object<OutTagType>> Cast(JNIEnv& env, const Class<OutTagType>& clazz, const T& object)
|
||
|
{
|
||
|
if (!object.IsInstanceOf(env, clazz))
|
||
|
{
|
||
|
ThrowNew(env, FindClass(env, "java/lang/ClassCastException"));
|
||
|
}
|
||
|
return Local<Object<OutTagType>>(env, reinterpret_cast<typename Object<OutTagType>::UntaggedType*>(NewLocal(env, object).release()));
|
||
|
}
|
||
|
}
|