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