JNI: Add test coverage for a jobjectArray in a native function

Make sure this works as it should. The bug report/support request wants
to have a String[] parameter on the Java side, but then the C++ side can
not use jobjectArray (as that has "[Ljava/lang/Object;" as signature),
so use Object[] instead (which is one solution; the other is to use
QList<jstring> or (in 6.8) QStringList on the C++ side.

What's easy to miss is that the jobjectArray that we get is a local ref,
so we have to extend its lifetime by creating a QJniObject holding it as
a global reference. We can then create a QJniArray from that QJniObject
(without any type safety).

Task-number: QTBUG-128456
Change-Id: I1e03b811165f9bc5106324d39fb58114ee8cf398
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Reviewed-by: Petri Virkkunen <petri.virkkunen@qt.io>
(cherry picked from commit f9fd5870f7379103005839bc03543bb8f6da94c3)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Volker Hilsheimer 2024-08-29 17:55:47 +02:00 committed by Qt Cherry-pick Bot
parent fbf052132e
commit d05438454f
2 changed files with 28 additions and 0 deletions

View File

@ -304,6 +304,7 @@ public class QtJniObjectTestClass
native public int callbackWithInt(int value);
native public int callbackWithDouble(double value);
native public int callbackWithJniArray(double[] value);
native public int callbackWithRawArray(Object[] value);
native public int callbackWithQList(double[] value);
native public int callbackWithStringList(String[] value);
@ -345,6 +346,10 @@ public class QtJniObjectTestClass
{
return callbackWithJniArray(value);
}
public int callMeBackWithRawArray(Object[] value)
{
return callbackWithRawArray(value);
}
public int callMeBackWithQList(double[] value)
{
return callbackWithQList(value);

View File

@ -1956,6 +1956,7 @@ enum class CallbackParameterType
Int,
Double,
JniArray,
RawArray,
QList,
QStringList,
};
@ -2022,6 +2023,14 @@ static int callbackWithJniArray(JNIEnv *, jobject, const QJniArray<jdouble> &val
}
Q_DECLARE_JNI_NATIVE_METHOD(callbackWithJniArray)
static std::optional<QJniObject> calledWithRawArray;
static int callbackWithRawArray(JNIEnv *, jobject, jobjectArray value)
{
calledWithRawArray.emplace(QJniObject(value));
return int(CallbackParameterType::RawArray);
}
Q_DECLARE_JNI_NATIVE_METHOD(callbackWithRawArray)
static std::optional<QList<double>> calledWithQList;
static int callbackWithQList(JNIEnv *, jobject, const QList<double> &value)
{
@ -2050,6 +2059,7 @@ void tst_QJniObject::callback_data()
QTest::addRow("Int") << CallbackParameterType::Int;
QTest::addRow("Double") << CallbackParameterType::Double;
QTest::addRow("JniArray") << CallbackParameterType::JniArray;
QTest::addRow("RawArray") << CallbackParameterType::RawArray;
QTest::addRow("QList") << CallbackParameterType::QList;
QTest::addRow("QStringList") << CallbackParameterType::QStringList;
}
@ -2128,6 +2138,19 @@ void tst_QJniObject::callback()
QCOMPARE(calledWithJniArray, doubles);
break;
}
case CallbackParameterType::RawArray: {
QVERIFY(TestClass::registerNativeMethods({
Q_JNI_NATIVE_METHOD(callbackWithRawArray)
}));
const QStringList strings{"a", "b", "c"};
const QJniArray stringArray(strings);
result = testObject.callMethod<int>("callMeBackWithRawArray",
stringArray.object<jobjectArray>());
QVERIFY(calledWithRawArray);
const auto stringsReceived = QJniArray<QString>(*calledWithRawArray).toContainer();
QCOMPARE(stringsReceived, strings);
break;
}
case CallbackParameterType::QList: {
QVERIFY(TestClass::registerNativeMethods({
Q_JNI_NATIVE_METHOD(callbackWithQList)