From f4eef861375744144e5ea0805b00748df2359c33 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Tue, 30 Jan 2024 15:21:38 +0100 Subject: [PATCH] JNI: implement support for native functions taking a list This didn't work yet because the partial specialization of the JNITypeForArgImpl factory was missing. Add a test case for QJniArray and QList. What doesn't work (yet) is QStringList for a native Java function taking a String[]. That will be added in a follow-up commit. Change-Id: I4d3fa0ecc04b98b9749f8358792f86c02ddbbc14 Reviewed-by: Assam Boudjelthia Reviewed-by: Marc Mutz --- src/corelib/kernel/qjnitypes.h | 27 ++++++++++++ .../testdata/QtJniObjectTestClass.java | 10 +++++ .../kernel/qjniobject/tst_qjniobject.cpp | 42 ++++++++++++++++++- 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qjnitypes.h b/src/corelib/kernel/qjnitypes.h index 978b0f0e8f..1eaae6312b 100644 --- a/src/corelib/kernel/qjnitypes.h +++ b/src/corelib/kernel/qjnitypes.h @@ -95,6 +95,33 @@ struct JNITypeForArgImpl } }; +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 QJniArray(t).toContainer(); + } +}; + template using JNITypeForArg = typename JNITypeForArgImpl>::Type; template diff --git a/tests/auto/corelib/kernel/qjniobject/testdata/src/org/qtproject/qt/android/testdata/QtJniObjectTestClass.java b/tests/auto/corelib/kernel/qjniobject/testdata/src/org/qtproject/qt/android/testdata/QtJniObjectTestClass.java index 14cc8d265d..386c6aa5c8 100644 --- a/tests/auto/corelib/kernel/qjniobject/testdata/src/org/qtproject/qt/android/testdata/QtJniObjectTestClass.java +++ b/tests/auto/corelib/kernel/qjniobject/testdata/src/org/qtproject/qt/android/testdata/QtJniObjectTestClass.java @@ -281,6 +281,8 @@ public class QtJniObjectTestClass native public int callbackWithBoolean(boolean value); native public int callbackWithInt(int value); native public int callbackWithDouble(double value); + native public int callbackWithJniArray(double[] value); + native public int callbackWithQList(double[] value); public int callMeBackWithObject(QtJniObjectTestClass that) { @@ -316,4 +318,12 @@ public class QtJniObjectTestClass { return callbackWithDouble(value); } + public int callMeBackWithJniArray(double[] value) + { + return callbackWithJniArray(value); + } + public int callMeBackWithQList(double[] value) + { + return callbackWithQList(value); + } } diff --git a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp index 2f7652dc3b..b462a69bef 100644 --- a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp +++ b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp @@ -1871,7 +1871,9 @@ enum class CallbackParameterType Byte, Boolean, Int, - Double + Double, + JniArray, + QList, }; static std::optional calledWithObject; @@ -1928,6 +1930,22 @@ static int callbackWithDouble(JNIEnv *, jobject, double value) } Q_DECLARE_JNI_NATIVE_METHOD(callbackWithDouble) +static std::optional> calledWithJniArray; +static int callbackWithJniArray(JNIEnv *, jobject, const QJniArray &value) +{ + calledWithJniArray.emplace(value); + return int(CallbackParameterType::JniArray); +} +Q_DECLARE_JNI_NATIVE_METHOD(callbackWithJniArray) + +static std::optional> calledWithQList; +static int callbackWithQList(JNIEnv *, jobject, const QList &value) +{ + calledWithQList.emplace(value); + return int(CallbackParameterType::QList); +} +Q_DECLARE_JNI_NATIVE_METHOD(callbackWithQList) + void tst_QJniObject::callback_data() { QTest::addColumn("parameterType"); @@ -1939,6 +1957,8 @@ void tst_QJniObject::callback_data() QTest::addRow("Boolean") << CallbackParameterType::Boolean; QTest::addRow("Int") << CallbackParameterType::Int; QTest::addRow("Double") << CallbackParameterType::Double; + QTest::addRow("JniArray") << CallbackParameterType::JniArray; + QTest::addRow("QList") << CallbackParameterType::QList; } void tst_QJniObject::callback() @@ -2005,6 +2025,26 @@ void tst_QJniObject::callback() QVERIFY(calledWithDouble); QCOMPARE(calledWithDouble.value(), 1.2345); break; + case CallbackParameterType::JniArray: { + QVERIFY(TestClass::registerNativeMethods({ + Q_JNI_NATIVE_METHOD(callbackWithJniArray) + })); + const QJniArray doubles = QJniArrayBase::fromContainer(QList{ 1.2, 3.4, 5.6 }); + result = testObject.callMethod("callMeBackWithJniArray", doubles); + QVERIFY(calledWithJniArray); + QCOMPARE(calledWithJniArray, doubles); + break; + } + case CallbackParameterType::QList: { + QVERIFY(TestClass::registerNativeMethods({ + Q_JNI_NATIVE_METHOD(callbackWithQList) + })); + const QList doubles = { 1.2, 3.4, 5.6 }; + result = testObject.callMethod("callMeBackWithQList", doubles); + QVERIFY(calledWithQList); + QCOMPARE(calledWithQList.value(), doubles); + break; + } } QCOMPARE(result, int(parameterType)); }