From 9f10fd8374e23fbfe9c207e68a03402df6e664d1 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Thu, 26 Dec 2024 19:18:57 +0100 Subject: [PATCH] JNI: Simplify type conversion for native functions, reuse existing code The QJniObject::LocalFrame has all the logic for converting between Qt types and corresponding JNI types. Instead of implementing the same type mapping for native function calls, reuse LocalFrame, with the special handling of cases where no conversion is necessary at all. Change-Id: I4a94b22788669387330ec1b3e27bb06eb6d64b7b Reviewed-by: Marc Mutz Reviewed-by: Volker Krause --- src/corelib/kernel/qjnitypes.h | 68 +++++++++------------------------- 1 file changed, 18 insertions(+), 50 deletions(-) diff --git a/src/corelib/kernel/qjnitypes.h b/src/corelib/kernel/qjnitypes.h index 367815c6f2d..29108b23f9b 100644 --- a/src/corelib/kernel/qjnitypes.h +++ b/src/corelib/kernel/qjnitypes.h @@ -127,64 +127,32 @@ QT_OVERLOADED_MACRO(Q_DECLARE_JNI_CLASS_SPECIALIZATION, __VA_ARGS__) namespace QtJniMethods { namespace Detail { -// Various helpers to forward the call to the registered function (with JNI types -// as arguments) to the real function with proper type conversion. This is needed -// because we want to write functions that take QJniObjects (subclasses), while -// Java can only call functions that take jobjects. - -// Map any QJniObject type to jobject +// A helper to forward the call to the registered function (with JNI types +// as arguments) to the real function, using the type conversion implemented in +// QJniObject::LocalFrame::convertTo/FromJni. This is needed because we want to +// write functions that take Qt-style arguments (QJniObject, declared types, +// QList etc), while Java can only call functions that take jobjects. template struct JNITypeForArgImpl { - using Type = std::conditional_t, - std::is_base_of>, - jobject, Arg>; - static Arg fromVarArg(Type t) + using LocalFrame = QtJniTypes::Detail::LocalFrame; + using JNIType = decltype(std::declval().convertToJni(std::declval())); + static Arg fromVarArg(JNIType t) // JNIType is always POD { - return static_cast(t); - } -}; - -template <> -struct JNITypeForArgImpl -{ - using Type = jstring; - - static QString fromVarArg(Type t) - { - return t ? QtJniTypes::Detail::toQString(t, QJniEnvironment::getJniEnv()) : QString(); - } -}; - -template -struct JNITypeForArgImpl> -{ - using Type = jobject; - - static QJniArray fromVarArg(Type t) - { - return QJniArray(t); - } -}; - -template -struct JNITypeForArgImpl> -{ -private: - using ArrayType = decltype(QJniArrayBase::fromContainer(std::declval>())); - using ArrayObjectType = decltype(std::declval().arrayObject()); - using ElementType = typename ArrayType::value_type; -public: - using Type = ArrayObjectType; - - static QList fromVarArg(Type t) - { - return t ? QJniArray(t).toContainer() : QList{}; + // Special case: if convertToJni doesn't do anything, don't do anything + // here either. convertFromJni would always give us a QJniObject (so + // that QJniObject::callMethod etc returns an owning QJniObject). + if constexpr (std::is_same_v) { + return t; + } else { + LocalFrame frame; + return frame.template convertFromJni(t); + } } }; template -using JNITypeForArg = typename JNITypeForArgImpl>::Type; +using JNITypeForArg = typename JNITypeForArgImpl>::JNIType; } // namespace Detail } // namespace QtJniMethods