JNI API review: refactor repeated if constexpr-chain
Provide class template specializations for each supported JNI type (and also covering the equivalent C++ types), and implement generic call- helpers using the type-specific JNI function. Remove the now unused static-assert helpers for unsupported types. We'll get compile time errors when the functions are used with unknown types. Change-Id: I8ae848bb9de60b536df64318c8a65560d8f70acb Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> (cherry picked from commit 85c36ef1ac0695b276f9fe583926a17d685982a6) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
7a6359c614
commit
f7e30e4ade
@ -582,36 +582,12 @@ private:
|
|||||||
friend bool operator==(const QJniObject &, const QJniObject &);
|
friend bool operator==(const QJniObject &, const QJniObject &);
|
||||||
friend bool operator!=(const QJniObject&, const QJniObject&);
|
friend bool operator!=(const QJniObject&, const QJniObject&);
|
||||||
|
|
||||||
template <typename Have, typename Want>
|
|
||||||
static constexpr bool sameTypeForJni = (QtJniTypes::Traits<Have>::signature()
|
|
||||||
== QtJniTypes::Traits<Want>::signature())
|
|
||||||
&& (sizeof(Have) == sizeof(Want));
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static constexpr void callMethodForType(JNIEnv *env, T &res, jobject obj,
|
static constexpr void callMethodForType(JNIEnv *env, T &res, jobject obj, jmethodID id, ...)
|
||||||
jmethodID id, ...)
|
|
||||||
{
|
{
|
||||||
va_list args = {};
|
va_list args = {};
|
||||||
va_start(args, id);
|
va_start(args, id);
|
||||||
|
QtJniTypes::Caller<T>::callMethodForType(env, res, obj, id, args);
|
||||||
if constexpr (sameTypeForJni<T, jboolean>)
|
|
||||||
res = T(env->CallBooleanMethodV(obj, id, args));
|
|
||||||
else if constexpr (sameTypeForJni<T, jbyte>)
|
|
||||||
res = T(env->CallByteMethodV(obj, id, args));
|
|
||||||
else if constexpr (sameTypeForJni<T, jchar>)
|
|
||||||
res = T(env->CallCharMethodV(obj, id, args));
|
|
||||||
else if constexpr (sameTypeForJni<T, jshort>)
|
|
||||||
res = T(env->CallShortMethodV(obj, id, args));
|
|
||||||
else if constexpr (sameTypeForJni<T, jint>)
|
|
||||||
res = T(env->CallIntMethodV(obj, id, args));
|
|
||||||
else if constexpr (sameTypeForJni<T, jlong>)
|
|
||||||
res = T(env->CallLongMethodV(obj, id, args));
|
|
||||||
else if constexpr (sameTypeForJni<T, jfloat>)
|
|
||||||
res = T(env->CallFloatMethodV(obj, id, args));
|
|
||||||
else if constexpr (sameTypeForJni<T, jdouble>)
|
|
||||||
res = T(env->CallDoubleMethodV(obj, id, args));
|
|
||||||
else
|
|
||||||
QtJniTypes::staticAssertTypeMismatch();
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,24 +599,7 @@ private:
|
|||||||
return;
|
return;
|
||||||
va_list args = {};
|
va_list args = {};
|
||||||
va_start(args, id);
|
va_start(args, id);
|
||||||
if constexpr (sameTypeForJni<T, jboolean>)
|
QtJniTypes::Caller<T>::callStaticMethodForType(env, res, clazz, id, args);
|
||||||
res = T(env->CallStaticBooleanMethodV(clazz, id, args));
|
|
||||||
else if constexpr (sameTypeForJni<T, jbyte>)
|
|
||||||
res = T(env->CallStaticByteMethodV(clazz, id, args));
|
|
||||||
else if constexpr (sameTypeForJni<T, jchar>)
|
|
||||||
res = T(env->CallStaticCharMethodV(clazz, id, args));
|
|
||||||
else if constexpr (sameTypeForJni<T, jshort>)
|
|
||||||
res = T(env->CallStaticShortMethodV(clazz, id, args));
|
|
||||||
else if constexpr (sameTypeForJni<T, jint>)
|
|
||||||
res = T(env->CallStaticIntMethodV(clazz, id, args));
|
|
||||||
else if constexpr (sameTypeForJni<T, jlong>)
|
|
||||||
res = T(env->CallStaticLongMethodV(clazz, id, args));
|
|
||||||
else if constexpr (sameTypeForJni<T, jfloat>)
|
|
||||||
res = T(env->CallStaticFloatMethodV(clazz, id, args));
|
|
||||||
else if constexpr (sameTypeForJni<T, jdouble>)
|
|
||||||
res = T(env->CallStaticDoubleMethodV(clazz, id, args));
|
|
||||||
else
|
|
||||||
QtJniTypes::staticAssertTypeMismatch();
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -656,105 +615,37 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static constexpr void getFieldForType(JNIEnv *env, T &res, jobject obj,
|
static constexpr void getFieldForType(JNIEnv *env, T &res, jobject obj, jfieldID id)
|
||||||
jfieldID id)
|
|
||||||
{
|
{
|
||||||
if constexpr (sameTypeForJni<T, jboolean>)
|
QtJniTypes::Caller<T>::getFieldForType(env, res, obj, id);
|
||||||
res = T(env->GetBooleanField(obj, id));
|
|
||||||
else if constexpr (sameTypeForJni<T, jbyte>)
|
|
||||||
res = T(env->GetByteField(obj, id));
|
|
||||||
else if constexpr (sameTypeForJni<T, jchar>)
|
|
||||||
res = T(env->GetCharField(obj, id));
|
|
||||||
else if constexpr (sameTypeForJni<T, jshort>)
|
|
||||||
res = T(env->GetShortField(obj, id));
|
|
||||||
else if constexpr (sameTypeForJni<T, jint>)
|
|
||||||
res = T(env->GetIntField(obj, id));
|
|
||||||
else if constexpr (sameTypeForJni<T, jlong>)
|
|
||||||
res = T(env->GetLongField(obj, id));
|
|
||||||
else if constexpr (sameTypeForJni<T, jfloat>)
|
|
||||||
res = T(env->GetFloatField(obj, id));
|
|
||||||
else if constexpr (sameTypeForJni<T, jdouble>)
|
|
||||||
res = T(env->GetDoubleField(obj, id));
|
|
||||||
else
|
|
||||||
QtJniTypes::staticAssertTypeMismatch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static constexpr void getStaticFieldForType(JNIEnv *env, T &res, jclass clazz,
|
static constexpr void getStaticFieldForType(JNIEnv *env, T &res, jclass clazz, jfieldID id)
|
||||||
jfieldID id)
|
|
||||||
{
|
{
|
||||||
if constexpr (sameTypeForJni<T, jboolean>)
|
QtJniTypes::Caller<T>::getStaticFieldForType(env, res, clazz, id);
|
||||||
res = T(env->GetStaticBooleanField(clazz, id));
|
|
||||||
else if constexpr (sameTypeForJni<T, jbyte>)
|
|
||||||
res = T(env->GetStaticByteField(clazz, id));
|
|
||||||
else if constexpr (sameTypeForJni<T, jchar>)
|
|
||||||
res = T(env->GetStaticCharField(clazz, id));
|
|
||||||
else if constexpr (sameTypeForJni<T, jshort>)
|
|
||||||
res = T(env->GetStaticShortField(clazz, id));
|
|
||||||
else if constexpr (sameTypeForJni<T, jint>)
|
|
||||||
res = T(env->GetStaticIntField(clazz, id));
|
|
||||||
else if constexpr (sameTypeForJni<T, jlong>)
|
|
||||||
res = T(env->GetStaticLongField(clazz, id));
|
|
||||||
else if constexpr (sameTypeForJni<T, jfloat>)
|
|
||||||
res = T(env->GetStaticFloatField(clazz, id));
|
|
||||||
else if constexpr (sameTypeForJni<T, jdouble>)
|
|
||||||
res = T(env->GetStaticDoubleField(clazz, id));
|
|
||||||
else
|
|
||||||
QtJniTypes::staticAssertTypeMismatch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static constexpr void setFieldForType(JNIEnv *env, jobject obj,
|
static constexpr void setFieldForType(JNIEnv *env, jobject obj, jfieldID id, T value)
|
||||||
jfieldID id, T value)
|
|
||||||
{
|
{
|
||||||
LocalFrame<T> frame(env);
|
if constexpr (QtJniTypes::isObjectType<T>()) {
|
||||||
if constexpr (sameTypeForJni<T, jboolean>)
|
LocalFrame<T> frame(env);
|
||||||
env->SetBooleanField(obj, id, static_cast<jboolean>(value));
|
|
||||||
else if constexpr (sameTypeForJni<T, jbyte>)
|
|
||||||
env->SetByteField(obj, id, static_cast<jbyte>(value));
|
|
||||||
else if constexpr (sameTypeForJni<T, jchar>)
|
|
||||||
env->SetCharField(obj, id, static_cast<jchar>(value));
|
|
||||||
else if constexpr (sameTypeForJni<T, jshort>)
|
|
||||||
env->SetShortField(obj, id, static_cast<jshort>(value));
|
|
||||||
else if constexpr (sameTypeForJni<T, jint>)
|
|
||||||
env->SetIntField(obj, id, static_cast<jint>(value));
|
|
||||||
else if constexpr (sameTypeForJni<T, jlong>)
|
|
||||||
env->SetLongField(obj, id, static_cast<jlong>(value));
|
|
||||||
else if constexpr (sameTypeForJni<T, jfloat>)
|
|
||||||
env->SetFloatField(obj, id, static_cast<jfloat>(value));
|
|
||||||
else if constexpr (sameTypeForJni<T, jdouble>)
|
|
||||||
env->SetDoubleField(obj, id, static_cast<jdouble>(value));
|
|
||||||
else if constexpr (QtJniTypes::isObjectType<T>())
|
|
||||||
env->SetObjectField(obj, id, static_cast<jobject>(frame.convertToJni(value)));
|
env->SetObjectField(obj, id, static_cast<jobject>(frame.convertToJni(value)));
|
||||||
else
|
} else {
|
||||||
QtJniTypes::staticAssertTypeMismatch();
|
QtJniTypes::Caller<T>::setFieldForType(env, obj, id, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static constexpr void setStaticFieldForType(JNIEnv *env, jclass clazz,
|
static constexpr void setStaticFieldForType(JNIEnv *env, jclass clazz, jfieldID id, T value)
|
||||||
jfieldID id, T value)
|
|
||||||
{
|
{
|
||||||
LocalFrame<T> frame(env);
|
if constexpr (QtJniTypes::isObjectType<T>()) {
|
||||||
if constexpr (sameTypeForJni<T, jboolean>)
|
LocalFrame<T> frame(env);
|
||||||
env->SetStaticBooleanField(clazz, id, static_cast<jboolean>(value));
|
|
||||||
else if constexpr (sameTypeForJni<T, jbyte>)
|
|
||||||
env->SetStaticByteField(clazz, id, static_cast<jbyte>(value));
|
|
||||||
else if constexpr (sameTypeForJni<T, jchar>)
|
|
||||||
env->SetStaticCharField(clazz, id, static_cast<jchar>(value));
|
|
||||||
else if constexpr (sameTypeForJni<T, jshort>)
|
|
||||||
env->SetStaticShortField(clazz, id, static_cast<jshort>(value));
|
|
||||||
else if constexpr (sameTypeForJni<T, jint>)
|
|
||||||
env->SetStaticIntField(clazz, id, static_cast<jint>(value));
|
|
||||||
else if constexpr (sameTypeForJni<T, jlong>)
|
|
||||||
env->SetStaticLongField(clazz, id, static_cast<jlong>(value));
|
|
||||||
else if constexpr (sameTypeForJni<T, jfloat>)
|
|
||||||
env->SetStaticFloatField(clazz, id, static_cast<jfloat>(value));
|
|
||||||
else if constexpr (sameTypeForJni<T, jdouble>)
|
|
||||||
env->SetStaticDoubleField(clazz, id, static_cast<jdouble>(value));
|
|
||||||
else if constexpr (QtJniTypes::isObjectType<T>())
|
|
||||||
env->SetStaticObjectField(clazz, id, static_cast<jobject>(frame.convertToJni(value)));
|
env->SetStaticObjectField(clazz, id, static_cast<jobject>(frame.convertToJni(value)));
|
||||||
else
|
} else {
|
||||||
QtJniTypes::staticAssertTypeMismatch();
|
QtJniTypes::Caller<T>::setStaticFieldForType(env, clazz, id, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
friend QJniObjectPrivate;
|
friend QJniObjectPrivate;
|
||||||
|
@ -138,19 +138,6 @@ template<> struct IsStringType<const char*, 0> : std::true_type {};
|
|||||||
template<size_t N> struct IsStringType<CTString<N>> : std::true_type {};
|
template<size_t N> struct IsStringType<CTString<N>> : std::true_type {};
|
||||||
template<size_t N> struct IsStringType<const char[N]> : std::true_type {};
|
template<size_t N> struct IsStringType<const char[N]> : std::true_type {};
|
||||||
|
|
||||||
template<bool flag = false>
|
|
||||||
static void staticAssertTypeMismatch()
|
|
||||||
{
|
|
||||||
static_assert(flag, "The used type is not supported by this template call. "
|
|
||||||
"Use a JNI based type instead.");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<bool flag = false>
|
|
||||||
static void staticAssertClassNotRegistered()
|
|
||||||
{
|
|
||||||
static_assert(flag, "Class not registered, use Q_DECLARE_JNI_CLASS");
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct Traits {
|
struct Traits {
|
||||||
// The return type of className/signature becomes void for any type
|
// The return type of className/signature becomes void for any type
|
||||||
@ -242,6 +229,56 @@ struct Traits {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Have, typename Want>
|
||||||
|
static constexpr bool sameTypeForJni = (QtJniTypes::Traits<Have>::signature()
|
||||||
|
== QtJniTypes::Traits<Want>::signature())
|
||||||
|
&& (sizeof(Have) == sizeof(Want));
|
||||||
|
|
||||||
|
template <typename, typename = void>
|
||||||
|
struct Caller
|
||||||
|
{};
|
||||||
|
|
||||||
|
#define MAKE_CALLER(Type, Method) \
|
||||||
|
template <typename T> \
|
||||||
|
struct Caller<T, std::enable_if_t<sameTypeForJni<T, Type>>> \
|
||||||
|
{ \
|
||||||
|
static constexpr void callMethodForType(JNIEnv *env, T &res, jobject obj, jmethodID id, va_list args) \
|
||||||
|
{ \
|
||||||
|
res = T(env->Call##Method##MethodV(obj, id, args)); \
|
||||||
|
} \
|
||||||
|
static constexpr void callStaticMethodForType(JNIEnv *env, T &res, jclass clazz, jmethodID id, va_list args) \
|
||||||
|
{ \
|
||||||
|
res = T(env->CallStatic##Method##MethodV(clazz, id, args)); \
|
||||||
|
} \
|
||||||
|
static constexpr void getFieldForType(JNIEnv *env, T &res, jobject obj, jfieldID id) \
|
||||||
|
{ \
|
||||||
|
res = T(env->Get##Method##Field(obj, id)); \
|
||||||
|
} \
|
||||||
|
static constexpr void getStaticFieldForType(JNIEnv *env, T &res, jclass clazz, jfieldID id) \
|
||||||
|
{ \
|
||||||
|
res = T(env->GetStatic##Method##Field(clazz, id)); \
|
||||||
|
} \
|
||||||
|
static constexpr void setFieldForType(JNIEnv *env, jobject obj, jfieldID id, T value) \
|
||||||
|
{ \
|
||||||
|
env->Set##Method##Field(obj, id, static_cast<Type>(value)); \
|
||||||
|
} \
|
||||||
|
static constexpr void setStaticFieldForType(JNIEnv *env, jclass clazz, jfieldID id, T value) \
|
||||||
|
{ \
|
||||||
|
env->SetStatic##Method##Field(clazz, id, static_cast<Type>(value)); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
MAKE_CALLER(jboolean, Boolean);
|
||||||
|
MAKE_CALLER(jbyte, Byte);
|
||||||
|
MAKE_CALLER(jchar, Char);
|
||||||
|
MAKE_CALLER(jshort, Short);
|
||||||
|
MAKE_CALLER(jint, Int);
|
||||||
|
MAKE_CALLER(jlong, Long);
|
||||||
|
MAKE_CALLER(jfloat, Float);
|
||||||
|
MAKE_CALLER(jdouble, Double);
|
||||||
|
|
||||||
|
#undef MAKE_CALLER
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static constexpr bool isPrimitiveType()
|
static constexpr bool isPrimitiveType()
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user