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<double> and QList<double>.

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 <assam.boudjelthia@qt.io>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
bb10
Volker Hilsheimer 2024-01-30 15:21:38 +01:00
parent 28572aad11
commit f4eef86137
3 changed files with 78 additions and 1 deletions

View File

@ -95,6 +95,33 @@ struct JNITypeForArgImpl<QString>
}
};
template <typename T>
struct JNITypeForArgImpl<QJniArray<T>>
{
using Type = jobject;
static QJniArray<T> fromVarArg(Type t)
{
return QJniArray<T>(t);
}
};
template <typename T>
struct JNITypeForArgImpl<QList<T>>
{
private:
using ArrayType = decltype(QJniArrayBase::fromContainer(std::declval<QList<T>>()));
using ArrayObjectType = decltype(std::declval<ArrayType>().arrayObject());
using ElementType = typename ArrayType::value_type;
public:
using Type = ArrayObjectType;
static QList<T> fromVarArg(Type t)
{
return QJniArray<ElementType>(t).toContainer();
}
};
template <typename Arg>
using JNITypeForArg = typename JNITypeForArgImpl<std::decay_t<Arg>>::Type;
template <typename Arg, typename Type>

View File

@ -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);
}
}

View File

@ -1871,7 +1871,9 @@ enum class CallbackParameterType
Byte,
Boolean,
Int,
Double
Double,
JniArray,
QList,
};
static std::optional<TestClass> calledWithObject;
@ -1928,6 +1930,22 @@ static int callbackWithDouble(JNIEnv *, jobject, double value)
}
Q_DECLARE_JNI_NATIVE_METHOD(callbackWithDouble)
static std::optional<QJniArray<jdouble>> calledWithJniArray;
static int callbackWithJniArray(JNIEnv *, jobject, const QJniArray<jdouble> &value)
{
calledWithJniArray.emplace(value);
return int(CallbackParameterType::JniArray);
}
Q_DECLARE_JNI_NATIVE_METHOD(callbackWithJniArray)
static std::optional<QList<double>> calledWithQList;
static int callbackWithQList(JNIEnv *, jobject, const QList<double> &value)
{
calledWithQList.emplace(value);
return int(CallbackParameterType::QList);
}
Q_DECLARE_JNI_NATIVE_METHOD(callbackWithQList)
void tst_QJniObject::callback_data()
{
QTest::addColumn<CallbackParameterType>("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<double> doubles = QJniArrayBase::fromContainer(QList<double>{ 1.2, 3.4, 5.6 });
result = testObject.callMethod<int>("callMeBackWithJniArray", doubles);
QVERIFY(calledWithJniArray);
QCOMPARE(calledWithJniArray, doubles);
break;
}
case CallbackParameterType::QList: {
QVERIFY(TestClass::registerNativeMethods({
Q_JNI_NATIVE_METHOD(callbackWithQList)
}));
const QList<double> doubles = { 1.2, 3.4, 5.6 };
result = testObject.callMethod<int>("callMeBackWithQList", doubles);
QVERIFY(calledWithQList);
QCOMPARE(calledWithQList.value(), doubles);
break;
}
}
QCOMPARE(result, int(parameterType));
}