diff --git a/src/corelib/kernel/qjniobject.cpp b/src/corelib/kernel/qjniobject.cpp index 045b9316cbd..8f21835a1fd 100644 --- a/src/corelib/kernel/qjniobject.cpp +++ b/src/corelib/kernel/qjniobject.cpp @@ -903,24 +903,26 @@ QJniObject QJniObject::callStaticObjectMethodV(jclass clazz, } /*! - \fn template Ret QJniObject::callMethod(const char *methodName, const char *signature, Args &&...args) const + \fn template auto QJniObject::callMethod(const char *methodName, const char *signature, Args &&...args) const \since 6.4 Calls the object's method \a methodName with \a signature specifying the types of any - subsequent arguments \a args. + subsequent arguments \a args, and returns the value (unless \c Ret is \c void). If \c Ret + is a jobject type, then the returned value will be a QJniObject. \code QJniObject myJavaStrin("org/qtproject/qt/TestClass"); jint index = myJavaString.callMethod("indexOf", "(I)I", 0x0051); \endcode - */ /*! - \fn template Ret QJniObject::callMethod(const char *methodName, Args &&...args) const + \fn template auto QJniObject::callMethod(const char *methodName, Args &&...args) const \since 6.4 - Calls the method \a methodName with arguments \a args and returns the value. + Calls the method \a methodName with arguments \a args and returns the value + (unless \c Ret is \c void). If \c Ret is a jobject type, then the returned value + will be a QJniObject. \code QJniObject myJavaStrin("org/qtproject/qt/TestClass"); @@ -931,11 +933,13 @@ QJniObject QJniObject::callStaticObjectMethodV(jclass clazz, */ /*! - \fn template Ret QJniObject::callStaticMethod(const char *className, const char *methodName, const char *signature, Args &&...args) + \fn template auto QJniObject::callStaticMethod(const char *className, const char *methodName, const char *signature, Args &&...args) \since 6.4 Calls the static method \a methodName from class \a className with \a signature - specifying the types of any subsequent arguments \a args. + specifying the types of any subsequent arguments \a args. Returns the result of + the method (unless \c Ret is \c void). If \c Ret is a jobject type, then the + returned value will be a QJniObject. \code jint a = 2; @@ -945,11 +949,12 @@ QJniObject QJniObject::callStaticObjectMethodV(jclass clazz, */ /*! - \fn template Ret QJniObject::callStaticMethod(const char *className, const char *methodName, Args &&...args) + \fn template auto QJniObject::callStaticMethod(const char *className, const char *methodName, Args &&...args) \since 6.4 Calls the static method \a methodName on class \a className with arguments \a args, - and returns the value of type \c Ret. + and returns the value of type \c Ret (unless \c Ret is \c void). If \c Ret + is a jobject type, then the returned value will be a QJniObject. \code jint value = QJniObject::callStaticMethod("MyClass", "staticMethod"); @@ -959,10 +964,12 @@ QJniObject QJniObject::callStaticObjectMethodV(jclass clazz, */ /*! - \fn template Ret QJniObject::callStaticMethod(jclass clazz, const char *methodName, const char *signature, Args &&...args) + \fn template auto QJniObject::callStaticMethod(jclass clazz, const char *methodName, const char *signature, Args &&...args) Calls the static method \a methodName from \a clazz with \a signature - specifying the types of any subsequent arguments. + specifying the types of any subsequent arguments. Returns the result of + the method (unless \c Ret is \c void). If \c Ret is a jobject type, then the + returned value will be a QJniObject. \code QJniEnvironment env; @@ -974,12 +981,15 @@ QJniObject QJniObject::callStaticObjectMethodV(jclass clazz, */ /*! - \fn template Ret QJniObject::callStaticMethod(jclass clazz, jmethodID methodId, Args &&...args) + \fn template auto QJniObject::callStaticMethod(jclass clazz, jmethodID methodId, Args &&...args) \since 6.4 Calls the static method identified by \a methodId from the class \a clazz - with any subsequent arguments. Useful when \a clazz and \a methodId are - already cached from previous operations. + with any subsequent arguments, and returns the value of type \c Ret (unless + \c Ret is \c void). If \c Ret is a jobject type, then the returned value will + be a QJniObject. + + Useful when \a clazz and \a methodId are already cached from previous operations. \code QJniEnvironment env; @@ -994,10 +1004,12 @@ QJniObject QJniObject::callStaticObjectMethodV(jclass clazz, */ /*! - \fn template Ret QJniObject::callStaticMethod(jclass clazz, const char *methodName, Args &&...args) + \fn template auto QJniObject::callStaticMethod(jclass clazz, const char *methodName, Args &&...args) \since 6.4 - Calls the static method \a methodName on \a clazz and returns the value. + Calls the static method \a methodName on \a clazz and returns the value of type \c Ret + (unless c Ret is \c void). If \c Ret if a jobject type, then the returned value will + be a QJniObject. \code QJniEnvironment env; diff --git a/src/corelib/kernel/qjniobject.h b/src/corelib/kernel/qjniobject.h index bb3f49c94fd..0d5c95b4052 100644 --- a/src/corelib/kernel/qjniobject.h +++ b/src/corelib/kernel/qjniobject.h @@ -55,35 +55,38 @@ public: QByteArray className() const; template - Ret callMethod(const char *methodName, const char *signature, Args &&...args) const + auto callMethod(const char *methodName, const char *signature, Args &&...args) const { - QtJniTypes::assertPrimitiveType(); - QJniEnvironment env; - jmethodID id = getCachedMethodID(env.jniEnv(), methodName, signature); - if (id) { - if constexpr (std::is_same::value) { - callVoidMethodV(env.jniEnv(), id, std::forward(args)...); - env.checkAndClearExceptions(); - } else { - Ret res{}; - callMethodForType(env.jniEnv(), res, object(), id, std::forward(args)...); - if (env.checkAndClearExceptions()) - res = {}; - return res; + if constexpr (QtJniTypes::isObjectType()) { + return callObjectMethod(methodName, signature, std::forward(args)...); + } else { + QtJniTypes::assertPrimitiveType(); + QJniEnvironment env; + jmethodID id = getCachedMethodID(env.jniEnv(), methodName, signature); + if (id) { + if constexpr (std::is_same::value) { + callVoidMethodV(env.jniEnv(), id, std::forward(args)...); + env.checkAndClearExceptions(); + } else { + Ret res{}; + callMethodForType(env.jniEnv(), res, object(), id, std::forward(args)...); + if (env.checkAndClearExceptions()) + res = {}; + return res; + } } + if constexpr (!std::is_same::value) + return Ret{}; } - if constexpr (!std::is_same::value) - return Ret{}; } template - Ret callMethod(const char *methodName, Args &&...args) const + auto callMethod(const char *methodName, Args &&...args) const { constexpr auto signature = QtJniTypes::methodSignature(); if constexpr (std::is_same::value) { callMethod(methodName, signature.data(), std::forward(args)...); } else { - QtJniTypes::assertPrimitiveType(); return callMethod(methodName, signature.data(), std::forward(args)...); } } @@ -99,61 +102,57 @@ public: QJniObject callObjectMethod(const char *methodName, const char *signature, ...) const; template - static Ret callStaticMethod(const char *className, const char *methodName, const char *signature, Args &&...args) + static auto callStaticMethod(const char *className, const char *methodName, const char *signature, Args &&...args) { - QtJniTypes::assertPrimitiveType(); QJniEnvironment env; jclass clazz = QJniObject::loadClass(className, env.jniEnv()); return callStaticMethod(clazz, methodName, signature, std::forward(args)...); } template - static Ret callStaticMethod(jclass clazz, const char *methodName, const char *signature, Args &&...args) + static auto callStaticMethod(jclass clazz, const char *methodName, const char *signature, Args &&...args) { - QtJniTypes::assertPrimitiveType(); QJniEnvironment env; - if (clazz) { - jmethodID id = getMethodID(env.jniEnv(), clazz, methodName, signature, true); - return callStaticMethod(clazz, id, std::forward(args)...); - } - if constexpr (!std::is_same::value) - return Ret{}; + jmethodID id = getMethodID(env.jniEnv(), clazz, methodName, signature, true); + return callStaticMethod(clazz, id, std::forward(args)...); } template - static Ret callStaticMethod(jclass clazz, jmethodID methodId, Args &&...args) + static auto callStaticMethod(jclass clazz, jmethodID methodId, Args &&...args) { - QtJniTypes::assertPrimitiveType(); - QJniEnvironment env; - if (clazz && methodId) { - if constexpr (std::is_same::value) { - callStaticMethodForVoid(env.jniEnv(), clazz, methodId, std::forward(args)...); - env.checkAndClearExceptions(); - } else { - Ret res{}; - callStaticMethodForType(env.jniEnv(), res, clazz, methodId, std::forward(args)...); - if (env.checkAndClearExceptions()) - res = {}; - return res; + if constexpr (QtJniTypes::isObjectType()) { + return callStaticObjectMethod(clazz, methodId, std::forward(args)...); + } else { + QtJniTypes::assertPrimitiveType(); + QJniEnvironment env; + if (clazz && methodId) { + if constexpr (std::is_same::value) { + callStaticMethodForVoid(env.jniEnv(), clazz, methodId, std::forward(args)...); + env.checkAndClearExceptions(); + } else { + Ret res{}; + callStaticMethodForType(env.jniEnv(), res, clazz, methodId, std::forward(args)...); + if (env.checkAndClearExceptions()) + res = {}; + return res; + } } + if constexpr (!std::is_same::value) + return Ret{}; } - if constexpr (!std::is_same::value) - return Ret{}; } template - static Ret callStaticMethod(const char *className, const char *methodName, Args &&...args) + static auto callStaticMethod(const char *className, const char *methodName, Args &&...args) { - QtJniTypes::assertPrimitiveType(); QJniEnvironment env; jclass clazz = QJniObject::loadClass(className, env.jniEnv()); return callStaticMethod(clazz, methodName, std::forward(args)...); } template - static Ret callStaticMethod(jclass clazz, const char *methodName, Args &&...args) + static auto callStaticMethod(jclass clazz, const char *methodName, Args &&...args) { - QtJniTypes::assertPrimitiveType(); constexpr auto signature = QtJniTypes::methodSignature(); return callStaticMethod(clazz, methodName, signature.data(), std::forward(args)...); } @@ -183,59 +182,71 @@ public: return callStaticObjectMethod(clazz, methodName, signature.data(), std::forward(args)...); } - template T getField(const char *fieldName) const + template auto getField(const char *fieldName) const { - QtJniTypes::assertPrimitiveType(); - QJniEnvironment env; - T res{}; - constexpr auto signature = QtJniTypes::fieldSignature(); - jfieldID id = getCachedFieldID(env.jniEnv(), fieldName, signature); - if (id) { - getFieldForType(env.jniEnv(), res, object(), id); - if (env.checkAndClearExceptions()) - res = {}; + if constexpr (QtJniTypes::isObjectType()) { + return getObjectField(fieldName); + } else { + QtJniTypes::assertPrimitiveType(); + QJniEnvironment env; + T res{}; + constexpr auto signature = QtJniTypes::fieldSignature(); + jfieldID id = getCachedFieldID(env.jniEnv(), fieldName, signature); + if (id) { + getFieldForType(env.jniEnv(), res, object(), id); + if (env.checkAndClearExceptions()) + res = {}; + } + return res; } - return res; } template - static T getStaticField(const char *className, const char *fieldName) + static auto getStaticField(const char *className, const char *fieldName) { - QtJniTypes::assertPrimitiveType(); - QJniEnvironment env; - jclass clazz = QJniObject::loadClass(className, env.jniEnv()); - if (!clazz) - return 0; + if constexpr (QtJniTypes::isObjectType()) { + return getStaticObjectField(className, fieldName); + } else { + QtJniTypes::assertPrimitiveType(); + QJniEnvironment env; + jclass clazz = QJniObject::loadClass(className, env.jniEnv()); + T res{}; + if (!clazz) + return res; - constexpr auto signature = QtJniTypes::fieldSignature(); - jfieldID id = getCachedFieldID(env.jniEnv(), clazz, - QJniObject::toBinaryEncClassName(className), - fieldName, - signature, true); - if (!id) - return 0; + constexpr auto signature = QtJniTypes::fieldSignature(); + jfieldID id = getCachedFieldID(env.jniEnv(), clazz, + QJniObject::toBinaryEncClassName(className), + fieldName, + signature, true); + if (!id) + return res; - T res{}; - getStaticFieldForType(env.jniEnv(), res, clazz, id); - if (env.checkAndClearExceptions()) - res = {}; - return res; - } - - template - static T getStaticField(jclass clazz, const char *fieldName) - { - QtJniTypes::assertPrimitiveType(); - QJniEnvironment env; - T res{}; - constexpr auto signature = QtJniTypes::fieldSignature(); - jfieldID id = getFieldID(env.jniEnv(), clazz, fieldName, signature, true); - if (id) { getStaticFieldForType(env.jniEnv(), res, clazz, id); if (env.checkAndClearExceptions()) res = {}; + return res; + } + } + + template + static auto getStaticField(jclass clazz, const char *fieldName) + { + if constexpr (QtJniTypes::isObjectType()) { + return getStaticObjectField(clazz, fieldName); + } else { + QtJniTypes::assertPrimitiveType(); + QJniEnvironment env; + T res{}; + constexpr auto signature = QtJniTypes::fieldSignature(); + jfieldID id = getFieldID(env.jniEnv(), clazz, fieldName, signature, true); + if (id) { + getStaticFieldForType(env.jniEnv(), res, clazz, id); + if (env.checkAndClearExceptions()) + res = {}; + } + return res; } - return res; } template diff --git a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp index 30c71ad798a..8faa9b6fbb8 100644 --- a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp +++ b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp @@ -201,6 +201,17 @@ void tst_QJniObject::callMethodTest() jlong ret = longObject.callMethod("longValue"); QCOMPARE(ret, jLong); } + + // as of Qt 6.4, callMethod works with an object type as well! + { + const QString qString = QLatin1String("Hello, Java"); + QJniObject jString = QJniObject::fromString(qString); + const QString qStringRet = jString.callMethod("toUpperCase").toString(); + QCOMPARE(qString.toUpper(), qStringRet); + + QJniObject subString = jString.callMethod("substring", 0, 4); + QCOMPARE(subString.toString(), qString.mid(0, 4)); + } } void tst_QJniObject::callObjectMethodTest() @@ -316,6 +327,17 @@ void tst_QJniObject::callStaticObjectMethod() returnedString = returnValue.toString(); QCOMPARE(returnedString, QString::fromLatin1("test format")); + + // from 6.4 on we can use callStaticMethod + returnValue = QJniObject::callStaticMethod(cls, + "format", + formatString.object(), + jobjectArray(0)); + QVERIFY(returnValue.isValid()); + + returnedString = returnValue.toString(); + + QCOMPARE(returnedString, QString::fromLatin1("test format")); } void tst_QJniObject::callStaticObjectMethodById() @@ -338,6 +360,15 @@ void tst_QJniObject::callStaticObjectMethodById() QString returnedString = returnValue.toString(); QCOMPARE(returnedString, QString::fromLatin1("test format")); + + // from Qt 6.4 on we can use callStaticMethod as well + returnValue = QJniObject::callStaticMethod( + cls, id, formatString.object(), jobjectArray(0)); + QVERIFY(returnValue.isValid()); + + returnedString = returnValue.toString(); + + QCOMPARE(returnedString, QString::fromLatin1("test format")); } void tst_QJniObject::callStaticBooleanMethod()