summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2023-09-14 21:15:20 +0200
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2023-10-16 18:43:16 +0200
commit80d4d55e250af1d643805bde3821987112cf09c1 (patch)
tree985611d8fcddadcdc7890479c83d8abdb9f3a5d5
parent53f9768e6424f7b00946005f82f11d82facee35a (diff)
JNI: add QJniArray class for easier working with arrays
Implements an iterator API and other standard member access functions for sequential containers so that we can use ranged-for over an object that is a jarray. Provides read-only access to individual elements (which is mostly relevant for arrays of objects), or the entire data() as a contiguous memory block (which is useful for arrays of primitive types). QJniObject call functions can return QJniArray<T> when the return type is either explicitly QJniArray<T> or T[], or their Qt equivalent (e.g. a jbyteArray can be taken or returned as a QByteArray). If the return type is a jarray type, then a QJniObject is returned as before. Arrays can be created from a Qt container through a constructor or the generic fromData named constructor in the QJniArrayBase class, which implements the generic logic. Not documented as public API yet. Added a compile-time test to verify that types are mapped correctly. The function test coverage is added to the QJniObject auto-test, as that already provides the Java test class with functions taking and returning arrays of different types. Change-Id: I0750fc4f4cce7314df3b10e122eafbcfd68297b6 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
-rw-r--r--src/corelib/CMakeLists.txt1
-rw-r--r--src/corelib/kernel/qjniarray.h356
-rw-r--r--src/corelib/kernel/qjniobject.h77
-rw-r--r--tests/auto/corelib/kernel/CMakeLists.txt1
-rw-r--r--tests/auto/corelib/kernel/qjniarray/CMakeLists.txt13
-rw-r--r--tests/auto/corelib/kernel/qjniarray/tst_qjniarray.cpp75
-rw-r--r--tests/auto/corelib/kernel/qjniobject/testdata/src/org/qtproject/qt/android/testdata/QtJniObjectTestClass.java99
-rw-r--r--tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp165
-rw-r--r--tests/auto/corelib/kernel/qjnitypes/tst_qjnitypes.cpp8
9 files changed, 770 insertions, 25 deletions
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index ca75bdf984..756d12f0bd 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -1000,6 +1000,7 @@ qt_internal_extend_target(Core CONDITION ANDROID
SOURCES
io/qstandardpaths_android.cpp
io/qstorageinfo_linux.cpp io/qstorageinfo_linux_p.h
+ kernel/qjniarray.h
kernel/qjnitypes.h kernel/qjnitypes_impl.h
kernel/qjnienvironment.cpp kernel/qjnienvironment.h
kernel/qjniobject.cpp kernel/qjniobject.h
diff --git a/src/corelib/kernel/qjniarray.h b/src/corelib/kernel/qjniarray.h
new file mode 100644
index 0000000000..ba79e27b8e
--- /dev/null
+++ b/src/corelib/kernel/qjniarray.h
@@ -0,0 +1,356 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QJNIARRAY_H
+#define QJNIARRAY_H
+
+#include <QtCore/qlist.h>
+
+#if defined(Q_QDOC) || defined(Q_OS_ANDROID)
+#include <QtCore/qbytearray.h>
+#include <QtCore/qjniobject.h>
+
+#include <utility>
+
+QT_BEGIN_NAMESPACE
+
+template <typename T> class QJniArray;
+template <typename T>
+struct QJniArrayIterator
+{
+ QJniArrayIterator(const QJniArrayIterator &other) = default;
+ QJniArrayIterator(QJniArrayIterator &&other) noexcept = default;
+ QJniArrayIterator &operator=(const QJniArrayIterator &other) = default;
+ QJniArrayIterator &operator=(QJniArrayIterator &&other) noexcept = default;
+
+ friend bool operator==(const QJniArrayIterator<T> &lhs, const QJniArrayIterator<T> &rhs) noexcept
+ {
+ return lhs.m_array == rhs.m_array && lhs.m_index == rhs.m_index;
+ }
+ friend bool operator!=(const QJniArrayIterator<T> &lhs, const QJniArrayIterator<T> &rhs) noexcept
+ {
+ return !(lhs == rhs);
+ }
+ const T operator*() const
+ {
+ return m_array->at(m_index);
+ }
+ friend QJniArrayIterator<T> &operator++(QJniArrayIterator<T> &that) noexcept
+ {
+ ++that.m_index;
+ return that;
+ }
+
+ void swap(QJniArrayIterator<T> &other) noexcept
+ {
+ std::swap(m_index, other.m_index);
+ std::swap(m_array, other.m_array);
+ }
+
+private:
+ friend class QJniArray<T>;
+
+ qsizetype m_index = 0;
+ const QJniArray<T> *m_array = nullptr;
+
+ QJniArrayIterator() = delete;
+ QJniArrayIterator(qsizetype index, const QJniArray<T> *array)
+ : m_index(index), m_array(array)
+ {}
+};
+
+class QJniArrayBase : public QJniObject
+{
+ // for SFINAE'ing out the fromContainer named constructor
+ template <typename Container, typename = void> struct CanConvertHelper : std::false_type {};
+ template <typename Container>
+ struct CanConvertHelper<Container, std::void_t<decltype(std::declval<Container>().data()),
+ decltype(std::declval<Container>().size())
+ >
+ > : std::true_type {};
+
+public:
+ QJniArrayBase(jarray array)
+ : QJniObject(static_cast<jobject>(array))
+ {
+ static_assert(sizeof(QJniArrayBase) == sizeof(QJniObject),
+ "QJniArrayBase must have the same size as QJniObject!");
+ }
+ QJniArrayBase(const QJniObject &object)
+ : QJniObject(object)
+ {}
+ QJniArrayBase(QJniObject &&object) noexcept
+ : QJniObject(std::move(object))
+ {}
+
+ qsizetype size() const
+ {
+ if (jarray array = object<jarray>())
+ return QJniEnvironment()->GetArrayLength(array);
+ return 0;
+ }
+
+ template <typename Container>
+ static constexpr bool CanConvert = CanConvertHelper<Container>::value;
+ template <typename Container
+ , std::enable_if_t<CanConvert<Container>, bool> = true
+ >
+ static auto fromContainer(Container &&container)
+ {
+ using ElementType = typename Container::value_type;
+ if constexpr (std::disjunction_v<std::is_same<ElementType, jobject>,
+ std::is_same<ElementType, QJniObject>>) {
+ return makeObjectArray(std::forward<Container>(container));
+ } else if constexpr (std::is_same_v<ElementType, jfloat>) {
+ return makeArray<jfloat>(std::forward<Container>(container), &JNIEnv::NewFloatArray,
+ &JNIEnv::SetFloatArrayRegion);
+ } else if constexpr (std::is_same_v<ElementType, jdouble>) {
+ return makeArray<jdouble>(std::forward<Container>(container), &JNIEnv::NewDoubleArray,
+ &JNIEnv::SetDoubleArrayRegion);
+ } else if constexpr (std::disjunction_v<std::is_same<ElementType, jboolean>,
+ std::is_same<ElementType, bool>>) {
+ return makeArray<jboolean>(std::forward<Container>(container), &JNIEnv::NewBooleanArray,
+ &JNIEnv::SetBooleanArrayRegion);
+ } else if constexpr (std::disjunction_v<std::is_same<ElementType, jbyte>,
+ std::is_same<ElementType, char>>) {
+ return makeArray<jbyte>(std::forward<Container>(container), &JNIEnv::NewByteArray,
+ &JNIEnv::SetByteArrayRegion);
+ } else if constexpr (std::disjunction_v<std::is_same<ElementType, jchar>,
+ std::is_same<ElementType, QChar>>) {
+ return makeArray<jchar>(std::forward<Container>(container), &JNIEnv::NewCharArray,
+ &JNIEnv::SetCharArrayRegion);
+ } else if constexpr (std::is_same_v<ElementType, jshort>
+ || sizeof(ElementType) == sizeof(jshort)) {
+ return makeArray<jshort>(std::forward<Container>(container), &JNIEnv::NewShortArray,
+ &JNIEnv::SetShortArrayRegion);
+ } else if constexpr (std::is_same_v<ElementType, jint>
+ || sizeof(ElementType) == sizeof(jint)) {
+ return makeArray<jint>(std::forward<Container>(container), &JNIEnv::NewIntArray,
+ &JNIEnv::SetIntArrayRegion);
+ } else if constexpr (std::is_same_v<ElementType, jlong>
+ || sizeof(ElementType) == sizeof(jlong)) {
+ return makeArray<jlong>(std::forward<Container>(container), &JNIEnv::NewLongArray,
+ &JNIEnv::SetLongArrayRegion);
+ }
+ }
+
+protected:
+ QJniArrayBase() = default;
+
+ template <typename ElementType, typename List, typename NewFn, typename SetFn>
+ static auto makeArray(List &&list, NewFn &&newArray, SetFn &&setRegion);
+ template <typename List>
+ static auto makeObjectArray(List &&list);
+};
+
+template <typename T>
+class QJniArray : public QJniArrayBase
+{
+ friend struct QJniArrayIterator<T>;
+public:
+ using Type = T;
+ using const_iterator = const QJniArrayIterator<T>;
+
+ using QJniArrayBase::QJniArrayBase;
+
+ template <typename Container
+ , std::enable_if_t<QJniArrayBase::CanConvert<Container>, bool> = true
+ >
+ explicit QJniArray(Container &&container);
+ ~QJniArray() = default;
+
+ auto arrayObject() const
+ {
+ if constexpr (std::is_convertible_v<jobject, T>)
+ return object<jobjectArray>();
+ else if constexpr (std::is_same_v<T, jbyte>)
+ return object<jbyteArray>();
+ else if constexpr (std::is_same_v<T, jchar>)
+ return object<jcharArray>();
+ else if constexpr (std::is_same_v<T, jboolean>)
+ return object<jbooleanArray>();
+ else if constexpr (std::is_same_v<T, jshort>)
+ return object<jshortArray>();
+ else if constexpr (std::is_same_v<T, jint>)
+ return object<jintArray>();
+ else if constexpr (std::is_same_v<T, jlong>)
+ return object<jlongArray>();
+ else if constexpr (std::is_same_v<T, jfloat>)
+ return object<jfloatArray>();
+ else if constexpr (std::is_same_v<T, jdouble>)
+ return object<jdoubleArray>();
+ else
+ return object<jarray>();
+ }
+
+ const_iterator begin() const { return {0, this}; }
+ const_iterator constBegin() const { return begin(); }
+ const_iterator cbegin() const { return begin(); }
+ const_iterator end() const { return {size(), this}; }
+ const_iterator constEnd() const { return {end()}; }
+ const_iterator cend() const { return {end()}; }
+
+ const T operator[](qsizetype i) const { return at(i); } // const return value to disallow assignment
+ T at(qsizetype i) const
+ {
+ QJniEnvironment env;
+ if constexpr (std::is_convertible_v<jobject, T>) {
+ return T{env->GetObjectArrayElement(object<jobjectArray>(), i)};
+ } else {
+ T res = {};
+ if constexpr (std::is_same_v<T, jbyte>)
+ env->GetByteArrayRegion(object<jbyteArray>(), i, 1, &res);
+ else if constexpr (std::is_same_v<T, jchar>)
+ env->GetCharArrayRegion(object<jcharArray>(), i, 1, &res);
+ else if constexpr (std::is_same_v<T, jboolean>)
+ env->GetBooleanArrayRegion(object<jbooleanArray>(), i, 1, &res);
+ else if constexpr (std::is_same_v<T, jshort>)
+ env->GetShortArrayRegion(object<jshortArray>(), i, 1, &res);
+ else if constexpr (std::is_same_v<T, jint>)
+ env->GetIntArrayRegion(object<jbyteArray>(), i, 1, &res);
+ else if constexpr (std::is_same_v<T, jlong>)
+ env->GetLongArrayRegion(object<jlongArray>(), i, 1, &res);
+ else if constexpr (std::is_same_v<T, jfloat>)
+ env->GetFloatArrayRegion(object<jfloatArray>(), i, 1, &res);
+ else if constexpr (std::is_same_v<T, jdouble>)
+ env->GetDoubleArrayRegion(object<jdoubleArray>(), i, 1, &res);
+ return res;
+ }
+ }
+ auto asContainer() const
+ {
+ QJniEnvironment env;
+ if constexpr (std::is_same_v<T, jobject>) {
+ QList<jobject> res;
+ res.reserve(size());
+ for (auto &&element : *this)
+ res.append(element);
+ return res;
+ } else if constexpr (std::is_same_v<T, jbyte>) {
+ const qsizetype bytecount = size();
+ QByteArray res(bytecount, Qt::Initialization::Uninitialized);
+ env->GetByteArrayRegion(object<jbyteArray>(),
+ 0, bytecount, reinterpret_cast<jbyte *>(res.data()));
+ return res;
+ } else {
+ QList<T> res;
+ res.resize(size());
+ if constexpr (std::is_same_v<T, jchar>) {
+ env->GetCharArrayRegion(object<jcharArray>(),
+ 0, res.size(), res.data());
+ } else if constexpr (std::is_same_v<T, jboolean>) {
+ env->GetBooleanArrayRegion(object<jbooleanArray>(),
+ 0, res.size(), res.data());
+ } else if constexpr (std::is_same_v<T, jshort>) {
+ env->GetShortArrayRegion(object<jshortArray>(),
+ 0, res.size(), res.data());
+ } else if constexpr (std::is_same_v<T, jint>) {
+ env->GetIntArrayRegion(object<jintArray>(),
+ 0, res.size(), res.data());
+ } else if constexpr (std::is_same_v<T, jlong>) {
+ env->GetLongArrayRegion(object<jlongArray>(),
+ 0, res.size(), res.data());
+ } else if constexpr (std::is_same_v<T, jfloat>) {
+ env->GetFloatArrayRegion(object<jfloatArray>(),
+ 0, res.size(), res.data());
+ } else if constexpr (std::is_same_v<T, jdouble>) {
+ env->GetDoubleArrayRegion(object<jdoubleArray>(),
+ 0, res.size(), res.data());
+ } else {
+ res.clear();
+ }
+ return res;
+ }
+ }
+};
+
+template <typename ElementType, typename List, typename NewFn, typename SetFn>
+auto QJniArrayBase::makeArray(List &&list, NewFn &&newArray, SetFn &&setRegion)
+{
+ const int length = int(list.size());
+ QJniEnvironment env;
+ JNIEnv *jenv = env.jniEnv();
+ auto localArray = (jenv->*newArray)(length);
+ if (env.checkAndClearExceptions())
+ return QJniArray<ElementType>();
+
+ // can't use static_cast here because we have signed/unsigned mismatches
+ if (length) {
+ (jenv->*setRegion)(localArray, 0, length,
+ reinterpret_cast<const ElementType *>(std::as_const(list).data()));
+ }
+ return QJniArray<ElementType>(localArray);
+};
+
+template <typename List>
+auto QJniArrayBase::makeObjectArray(List &&list)
+{
+ using ElementType = typename List::value_type;
+ if (list.isEmpty())
+ return QJniArray<jobject>();
+
+ QJniEnvironment env;
+ const int length = int(list.size());
+
+ // this assumes that all objects in the list have the same class
+ jclass elementClass = nullptr;
+ if constexpr (std::is_same_v<ElementType, QJniObject>)
+ elementClass = list.first().objectClass();
+ else
+ elementClass = env->GetObjectClass(list.first());
+ auto localArray = env->NewObjectArray(length, elementClass, nullptr);
+ if (env.checkAndClearExceptions())
+ return QJniArray<jobject>();
+ for (int i = 0; i < length; ++i) {
+ jobject object;
+ if constexpr (std::is_same_v<ElementType, QJniObject>)
+ object = list.at(i).object();
+ else
+ object = list.at(i);
+ env->SetObjectArrayElement(localArray, i, object);
+ }
+ return QJniArray<jobject>(localArray);
+}
+
+
+template <typename T>
+template <typename Container
+ , std::enable_if_t<QJniArrayBase::CanConvert<Container>, bool>
+>
+QJniArray<T>::QJniArray(Container &&container)
+ : QJniArrayBase()
+{
+ *this = QJniArrayBase::fromContainer(std::forward<Container>(container));
+}
+
+namespace QtJniTypes
+{
+template <typename T> struct IsJniArray: std::false_type {};
+template <typename T> struct IsJniArray<QJniArray<T>> : std::true_type {};
+template <typename T> struct Traits<QJniArray<T>> {
+ template <ValidFieldType<T> = true>
+ static constexpr auto signature()
+ {
+ return CTString("[") + Traits<T>::signature();
+ }
+};
+template <typename T> struct Traits<QList<T>> {
+ template <ValidFieldType<T> = true>
+ static constexpr auto signature()
+ {
+ return CTString("[") + Traits<T>::signature();
+ }
+};
+template <> struct Traits<QByteArray> {
+ static constexpr auto signature()
+ {
+ return CTString("[B");
+ }
+};
+}
+
+QT_END_NAMESPACE
+
+#endif
+
+#endif // QJNIARRAY_H
diff --git a/src/corelib/kernel/qjniobject.h b/src/corelib/kernel/qjniobject.h
index 6fe646d50f..0ba7209b85 100644
--- a/src/corelib/kernel/qjniobject.h
+++ b/src/corelib/kernel/qjniobject.h
@@ -37,30 +37,9 @@ class Q_CORE_EXPORT QJniObject
bool checkAndClearExceptions() { return env.checkAndClearExceptions(); }
template <typename T>
- auto convertToJni(T &&value)
- {
- using Type = q20::remove_cvref_t<T>;
- if constexpr (std::is_same_v<Type, QString>) {
- return newLocalRef<jstring>(QJniObject::fromString(value));
- } else if constexpr (std::is_base_of_v<QJniObject, Type>) {
- return value.object();
- } else {
- return static_cast<T &&>(value);
- }
- }
+ auto convertToJni(T &&value);
template <typename T>
- auto convertFromJni(QJniObject &&object)
- {
- using Type = q20::remove_cvref_t<T>;
- if constexpr (std::is_same_v<Type, QString>) {
- return object.toString();
- } else if constexpr (std::is_base_of_v<QJniObject, Type>
- && !std::is_same_v<QJniObject, Type>) {
- return T{std::move(object)};
- } else {
- return std::move(object);
- }
- }
+ auto convertFromJni(QJniObject &&object);
};
public:
QJniObject();
@@ -779,6 +758,58 @@ inline bool operator!=(const QJniObject &obj1, const QJniObject &obj2)
return !obj1.isSameObject(obj2);
}
+// This cannot be included earlier as QJniArray is a QJniObject subclass, but it
+// must be included so that we can implement QJniObject::LocalFrame conversion.
+#include <QtCore/qjniarray.h>
+
+template <typename ...Args>
+template <typename T>
+auto QJniObject::LocalFrame<Args...>::convertToJni(T &&value)
+{
+ using Type = q20::remove_cvref_t<T>;
+ if constexpr (std::is_same_v<Type, QString>) {
+ return newLocalRef<jstring>(QJniObject::fromString(value));
+ } else if constexpr (QtJniTypes::IsJniArray<Type>::value) {
+ return value.arrayObject();
+ } else if constexpr (QJniArrayBase::CanConvert<T>) {
+ using QJniArrayType = decltype(QJniArrayBase::fromContainer(std::forward<T>(value)));
+ using ArrayType = decltype(std::declval<QJniArrayType>().arrayObject());
+ return newLocalRef<ArrayType>(QJniArrayBase::fromContainer(std::forward<T>(value)).template object<jobject>());
+ } else if constexpr (std::is_base_of_v<QJniObject, Type>) {
+ return value.object();
+ } else {
+ return static_cast<T &&>(value);
+ }
+}
+
+template <typename ...Args>
+template <typename T>
+auto QJniObject::LocalFrame<Args...>::convertFromJni(QJniObject &&object)
+{
+ using Type = q20::remove_cvref_t<T>;
+ if constexpr (std::is_same_v<Type, QString>) {
+ return object.toString();
+ } else if constexpr (QtJniTypes::IsJniArray<Type>::value) {
+ return T{object};
+ } else if constexpr (QJniArrayBase::CanConvert<Type>) {
+ // if we were to create a QJniArray from Type...
+ using QJniArrayType = decltype(QJniArrayBase::fromContainer(std::declval<Type>()));
+ // then that QJniArray would have elements of type
+ using ElementType = typename QJniArrayType::Type;
+ // construct a QJniArray from a jobject pointer of that type
+ return QJniArray<ElementType>(object.template object<jarray>()).asContainer();
+ } else if constexpr (std::is_array_v<Type>) {
+ using ElementType = std::remove_extent_t<Type>;
+ return QJniArray<ElementType>{object};
+ } else if constexpr (std::is_base_of_v<QJniObject, Type>
+ && !std::is_same_v<QJniObject, Type>) {
+ return T{std::move(object)};
+ } else {
+ return std::move(object);
+ }
+}
+
+
QT_END_NAMESPACE
#endif
diff --git a/tests/auto/corelib/kernel/CMakeLists.txt b/tests/auto/corelib/kernel/CMakeLists.txt
index ce0e82bae2..130fc080b6 100644
--- a/tests/auto/corelib/kernel/CMakeLists.txt
+++ b/tests/auto/corelib/kernel/CMakeLists.txt
@@ -49,4 +49,5 @@ if(ANDROID)
add_subdirectory(qjnienvironment)
add_subdirectory(qjniobject)
add_subdirectory(qjnitypes)
+ add_subdirectory(qjniarray)
endif()
diff --git a/tests/auto/corelib/kernel/qjniarray/CMakeLists.txt b/tests/auto/corelib/kernel/qjniarray/CMakeLists.txt
new file mode 100644
index 0000000000..308b2c6427
--- /dev/null
+++ b/tests/auto/corelib/kernel/qjniarray/CMakeLists.txt
@@ -0,0 +1,13 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qjnitypes LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_qjniarray
+ SOURCES
+ tst_qjniarray.cpp
+)
diff --git a/tests/auto/corelib/kernel/qjniarray/tst_qjniarray.cpp b/tests/auto/corelib/kernel/qjniarray/tst_qjniarray.cpp
new file mode 100644
index 0000000000..fa0da3ca66
--- /dev/null
+++ b/tests/auto/corelib/kernel/qjniarray/tst_qjniarray.cpp
@@ -0,0 +1,75 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include <QtTest>
+
+#include <QtCore/qjnitypes.h>
+#include <QtCore/qjniarray.h>
+
+using namespace Qt::StringLiterals;
+
+class tst_QJniArray : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QJniArray() = default;
+};
+
+using namespace QtJniTypes;
+
+// fake type so that we can compile-time test and assert correct type mappings
+Q_DECLARE_JNI_CLASS(List, "qt/test/List");
+
+// verify that we get the return type we expect for the specified return type
+#define VERIFY_RETURN_FOR_TYPE(In, Out) \
+static_assert(std::is_same_v<decltype(List::callStaticMethod<In>("toByteArray")), Out>)
+
+VERIFY_RETURN_FOR_TYPE(jobjectArray, QJniObject);
+VERIFY_RETURN_FOR_TYPE(jobject[], QJniArray<jobject>);
+//VERIFY_RETURN_FOR_TYPE(QList<QJniObject>, QList<QJniObject>);
+VERIFY_RETURN_FOR_TYPE(QList<jobject>, QList<jobject>);
+
+VERIFY_RETURN_FOR_TYPE(jbyteArray, QJniObject);
+VERIFY_RETURN_FOR_TYPE(jbyte[], QJniArray<jbyte>);
+VERIFY_RETURN_FOR_TYPE(QByteArray, QByteArray);
+
+VERIFY_RETURN_FOR_TYPE(jbooleanArray, QJniObject);
+VERIFY_RETURN_FOR_TYPE(jboolean[], QJniArray<jboolean>);
+VERIFY_RETURN_FOR_TYPE(QList<jboolean>, QList<jboolean>);
+VERIFY_RETURN_FOR_TYPE(QList<bool>, QList<jboolean>);
+
+VERIFY_RETURN_FOR_TYPE(jcharArray, QJniObject);
+VERIFY_RETURN_FOR_TYPE(jchar[], QJniArray<jchar>);
+VERIFY_RETURN_FOR_TYPE(QList<jchar>, QList<jchar>);
+
+VERIFY_RETURN_FOR_TYPE(jshortArray, QJniObject);
+VERIFY_RETURN_FOR_TYPE(jshort[], QJniArray<jshort>);
+VERIFY_RETURN_FOR_TYPE(QList<jshort>, QList<jshort>);
+VERIFY_RETURN_FOR_TYPE(QList<short>, QList<short>);
+
+VERIFY_RETURN_FOR_TYPE(jintArray, QJniObject);
+VERIFY_RETURN_FOR_TYPE(jint[], QJniArray<jint>);
+VERIFY_RETURN_FOR_TYPE(QList<jint>, QList<jint>);
+VERIFY_RETURN_FOR_TYPE(QList<int>, QList<int>);
+
+VERIFY_RETURN_FOR_TYPE(jlongArray, QJniObject);
+VERIFY_RETURN_FOR_TYPE(jlong[], QJniArray<jlong>);
+VERIFY_RETURN_FOR_TYPE(QList<jlong>, QList<jlong>);
+// VERIFY_RETURN_FOR_TYPE(QList<long>, QList<long>); // assumes long is 64bit
+
+VERIFY_RETURN_FOR_TYPE(jfloatArray, QJniObject);
+VERIFY_RETURN_FOR_TYPE(jfloat[], QJniArray<jfloat>);
+VERIFY_RETURN_FOR_TYPE(QList<jfloat>, QList<jfloat>);
+VERIFY_RETURN_FOR_TYPE(QList<float>, QList<float>);
+
+VERIFY_RETURN_FOR_TYPE(jdoubleArray, QJniObject);
+VERIFY_RETURN_FOR_TYPE(jdouble[], QJniArray<jdouble>);
+VERIFY_RETURN_FOR_TYPE(QList<jdouble>, QList<jdouble>);
+VERIFY_RETURN_FOR_TYPE(QList<double>, QList<double>);
+
+VERIFY_RETURN_FOR_TYPE(QString, QString);
+
+QTEST_MAIN(tst_QJniArray)
+
+#include "tst_qjniarray.moc"
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 d1b4ea480e..b56447198f 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
@@ -135,44 +135,143 @@ public class QtJniObjectTestClass
public static Object[] staticObjectArrayMethod()
{ Object[] array = { new Object(), new Object(), new Object() }; return array; }
public Object[] objectArrayMethod() { return staticObjectArrayMethod(); }
+ public static Object[] staticReverseObjectArray(Object[] array)
+ {
+ for (int i = 0; i < array.length / 2; ++i) {
+ Object old = array[array.length - i - 1];
+ array[array.length - i - 1] = array[i];
+ array[i] = old;
+ }
+ return array;
+ }
+ public Object[] reverseObjectArray(Object[] array)
+ { return staticReverseObjectArray(array); }
// --------------------------------------------------------------------------------------------
public static boolean[] staticBooleanArrayMethod()
{ boolean[] array = { true, true, true }; return array; }
public boolean[] booleanArrayMethod() { return staticBooleanArrayMethod(); }
+ public static boolean[] staticReverseBooleanArray(boolean[] array)
+ {
+ for (int i = 0; i < array.length / 2; ++i) {
+ boolean old = array[array.length - i - 1];
+ array[array.length - i - 1] = array[i];
+ array[i] = old;
+ }
+ return array;
+ }
+ public boolean[] reverseBooleanArray(boolean[] array)
+ { return staticReverseBooleanArray(array); }
// --------------------------------------------------------------------------------------------
public static byte[] staticByteArrayMethod()
{ byte[] array = { 'a', 'b', 'c' }; return array; }
public byte[] byteArrayMethod() { return staticByteArrayMethod(); }
+ public static byte[] staticReverseByteArray(byte[] array)
+ {
+ for (int i = 0; i < array.length / 2; ++i) {
+ byte old = array[array.length - i - 1];
+ array[array.length - i - 1] = array[i];
+ array[i] = old;
+ }
+ return array;
+ }
+ public byte[] reverseByteArray(byte[] array)
+ { return staticReverseByteArray(array); }
// --------------------------------------------------------------------------------------------
public static char[] staticCharArrayMethod()
{ char[] array = { 'a', 'b', 'c' }; return array; }
public char[] charArrayMethod() { return staticCharArrayMethod(); }
+ public static char[] staticReverseCharArray(char[] array)
+ {
+ for (int i = 0; i < array.length / 2; ++i) {
+ char old = array[array.length - i - 1];
+ array[array.length - i - 1] = array[i];
+ array[i] = old;
+ }
+ return array;
+ }
+ public char[] reverseCharArray(char[] array)
+ { return staticReverseCharArray(array); }
// --------------------------------------------------------------------------------------------
public static short[] staticShortArrayMethod() { short[] array = { 3, 2, 1 }; return array; }
public short[] shortArrayMethod() { return staticShortArrayMethod(); }
+ public static short[] staticReverseShortArray(short[] array)
+ {
+ for (int i = 0; i < array.length / 2; ++i) {
+ short old = array[array.length - i - 1];
+ array[array.length - i - 1] = array[i];
+ array[i] = old;
+ }
+ return array;
+ }
+ public short[] reverseShortArray(short[] array)
+ { return staticReverseShortArray(array); }
// --------------------------------------------------------------------------------------------
public static int[] staticIntArrayMethod() { int[] array = { 3, 2, 1 }; return array; }
public int[] intArrayMethod() { return staticIntArrayMethod(); }
+ public static int[] staticReverseIntArray(int[] array)
+ {
+ for (int i = 0; i < array.length / 2; ++i) {
+ int old = array[array.length - i - 1];
+ array[array.length - i - 1] = array[i];
+ array[i] = old;
+ }
+ return array;
+ }
+ public int[] reverseIntArray(int[] array)
+ { return staticReverseIntArray(array); }
// --------------------------------------------------------------------------------------------
public static long[] staticLongArrayMethod()
{ long[] array = { 3, 2, 1 }; return array; }
public long[] longArrayMethod() { return staticLongArrayMethod(); }
+ public static long[] staticReverseLongArray(long[] array)
+ {
+ for (int i = 0; i < array.length / 2; ++i) {
+ long old = array[array.length - i - 1];
+ array[array.length - i - 1] = array[i];
+ array[i] = old;
+ }
+ return array;
+ }
+ public long[] reverseLongArray(long[] array)
+ { return staticReverseLongArray(array); }
// --------------------------------------------------------------------------------------------
public static float[] staticFloatArrayMethod()
{ float[] array = { 1.0f, 2.0f, 3.0f }; return array; }
public float[] floatArrayMethod() { return staticFloatArrayMethod(); }
+ public static float[] staticReverseFloatArray(float[] array)
+ {
+ for (int i = 0; i < array.length / 2; ++i) {
+ float old = array[array.length - i - 1];
+ array[array.length - i - 1] = array[i];
+ array[i] = old;
+ }
+ return array;
+ }
+ public float[] reverseFloatArray(float[] array)
+ { return staticReverseFloatArray(array); }
// --------------------------------------------------------------------------------------------
public static double[] staticDoubleArrayMethod()
{ double[] array = { 3.0, 2.0, 1.0 }; return array; }
public double[] doubleArrayMethod() { return staticDoubleArrayMethod(); }
+ public static double[] staticReverseDoubleArray(double[] array)
+ {
+ for (int i = 0; i < array.length / 2; ++i) {
+ double old = array[array.length - i - 1];
+ array[array.length - i - 1] = array[i];
+ array[i] = old;
+ }
+ return array;
+ }
+ public double[] reverseDoubleArray(double[] array)
+ { return staticReverseDoubleArray(array); }
// --------------------------------------------------------------------------------------------
native public int callbackWithObject(QtJniObjectTestClass that);
diff --git a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp
index 47c3a707f0..751e5a84d8 100644
--- a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp
+++ b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp
@@ -1495,6 +1495,18 @@ void tst_QJniObject::templateApiCheck()
const auto array = TestClass::callStaticMethod<jobject[]>("staticObjectArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+
+ QJniArray<jobject> newArray(QList<QJniObject>{QJniObject::fromString(u"one"_s),
+ QJniObject::fromString(u"two"_s),
+ QJniObject::fromString(u"three"_s)});
+ QVERIFY(newArray.isValid());
+ const auto reverse = TestClass::callStaticMethod<jobject[]>("staticReverseObjectArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.size(), 3);
+ QCOMPARE(QJniObject(reverse.at(0)).toString(), u"three"_s);
+ QCOMPARE(QJniObject(reverse.at(1)).toString(), u"two"_s);
+ QCOMPARE(QJniObject(reverse.at(2)).toString(), u"one"_s);
}
{
@@ -1503,6 +1515,18 @@ void tst_QJniObject::templateApiCheck()
const auto array = testClass.callMethod<jobject[]>("objectArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+
+ QJniArray<jobject> newArray(QList<QJniObject>{QJniObject::fromString(u"one"_s),
+ QJniObject::fromString(u"two"_s),
+ QJniObject::fromString(u"three"_s)});
+ QVERIFY(newArray.isValid());
+ const auto reverse = testClass.callMethod<jobject[]>("reverseObjectArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.size(), 3);
+ QCOMPARE(QJniObject(reverse.at(0)).toString(), u"three"_s);
+ QCOMPARE(QJniObject(reverse.at(1)).toString(), u"two"_s);
+ QCOMPARE(QJniObject(reverse.at(2)).toString(), u"one"_s);
}
// jbooleanArray ------------------------------------------------------------------------------
@@ -1513,6 +1537,14 @@ void tst_QJniObject::templateApiCheck()
const auto array = TestClass::callStaticMethod<jboolean[]>("staticBooleanArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+ QCOMPARE(array.asContainer(), (QList<jboolean>{true, true, true}));
+
+ QJniArray<jboolean> newArray(QList<jboolean>{true, false, false});
+ QVERIFY(newArray.isValid());
+ const auto reverse = TestClass::callStaticMethod<jboolean[]>("staticReverseBooleanArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.asContainer(), (QList<jboolean>{false, false, true}));
}
{
@@ -1521,6 +1553,14 @@ void tst_QJniObject::templateApiCheck()
const auto array = testClass.callMethod<jboolean[]>("booleanArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+ QCOMPARE(array.asContainer(), (QList<jboolean>{true, true, true}));
+
+ QJniArray<jboolean> newArray(QList<jboolean>{true, false, false});
+ QVERIFY(newArray.isValid());
+ const auto reverse = testClass.callMethod<jboolean[]>("reverseBooleanArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.asContainer(), (QList<jboolean>{false, false, true}));
}
// jbyteArray ---------------------------------------------------------------------------------
@@ -1531,6 +1571,18 @@ void tst_QJniObject::templateApiCheck()
const auto array = TestClass::callStaticMethod<jbyte[]>("staticByteArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+ QCOMPARE(array.asContainer(), "abc");
+
+ QJniArray<jbyte> newArray(QByteArray{"cba"});
+ QVERIFY(newArray.isValid());
+ const auto reverse = TestClass::callStaticMethod<jbyte[]>("staticReverseByteArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.asContainer(), "abc");
+
+ const QByteArray reverse2 = TestClass::callStaticMethod<QByteArray>("staticReverseByteArray",
+ QByteArray("abc"));
+ QCOMPARE(reverse2, "cba");
}
{
@@ -1539,6 +1591,14 @@ void tst_QJniObject::templateApiCheck()
const auto array = testClass.callMethod<jbyte[]>("byteArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+ QCOMPARE(array.asContainer(), "abc");
+
+ QJniArray<jbyte> newArray = QJniArrayBase::fromContainer(QByteArray{"cba"});
+ QVERIFY(newArray.isValid());
+ const auto reverse = testClass.callMethod<jbyte[]>("reverseByteArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.asContainer(), "abc");
}
// jcharArray ---------------------------------------------------------------------------------
@@ -1549,6 +1609,18 @@ void tst_QJniObject::templateApiCheck()
const auto array = TestClass::callStaticMethod<jchar[]>("staticCharArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+ QCOMPARE(array.asContainer(), (QList<jchar>{u'a', u'b', u'c'}));
+
+ QJniArray<jchar> newArray(QList<jchar>{u'c', u'b', u'a'});
+ QVERIFY(newArray.isValid());
+ const auto reverse = TestClass::callStaticMethod<jchar[]>("staticReverseCharArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.asContainer(), (QList<jchar>{u'a', u'b', u'c'}));
+
+ const QList<jchar> reverse2 = TestClass::callStaticMethod<QList<jchar>>("staticReverseCharArray",
+ (QList<jchar>{u'c', u'b', u'a'}));
+ QCOMPARE(reverse2, (QList<jchar>{u'a', u'b', u'c'}));
}
{
@@ -1557,6 +1629,14 @@ void tst_QJniObject::templateApiCheck()
const auto array = testClass.callMethod<jchar[]>("charArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+ QCOMPARE(array.asContainer(), (QList<jchar>{u'a', u'b', u'c'}));
+
+ QJniArray<jchar> newArray = QJniArrayBase::fromContainer(QList<jchar>{u'c', u'b', u'a'});
+ QVERIFY(newArray.isValid());
+ const auto reverse = testClass.callMethod<jchar[]>("reverseCharArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.asContainer(), (QList<jchar>{u'a', u'b', u'c'}));
}
// jshortArray --------------------------------------------------------------------------------
@@ -1567,6 +1647,18 @@ void tst_QJniObject::templateApiCheck()
const auto array = TestClass::callStaticMethod<jshort[]>("staticShortArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+ QCOMPARE(array.asContainer(), (QList<jshort>{3, 2, 1}));
+
+ QJniArray<jshort> newArray(QList<jshort>{3, 2, 1});
+ QVERIFY(newArray.isValid());
+ const auto reverse = TestClass::callStaticMethod<jshort[]>("staticReverseShortArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.asContainer(), (QList<jshort>{1, 2, 3}));
+
+ const QList<jshort> reverse2 = TestClass::callStaticMethod<QList<jshort>>("staticReverseShortArray",
+ (QList<jshort>{1, 2, 3}));
+ QCOMPARE(reverse2, (QList<jshort>{3, 2, 1}));
}
{
@@ -1575,6 +1667,15 @@ void tst_QJniObject::templateApiCheck()
const auto array = testClass.callMethod<jshort[]>("shortArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+ QCOMPARE(array.asContainer(), (QList<jshort>{3, 2, 1}));
+
+ QJniArray<jshort> newArray = QJniArrayBase::fromContainer(QList<jshort>{3, 2, 1});
+ static_assert(std::is_same_v<decltype(newArray)::Type, jshort>);
+ QVERIFY(newArray.isValid());
+ const auto reverse = testClass.callMethod<jshort[]>("reverseShortArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.asContainer(), (QList<jshort>{1, 2, 3}));
}
// jintArray ----------------------------------------------------------------------------------
@@ -1585,6 +1686,14 @@ void tst_QJniObject::templateApiCheck()
const auto array = TestClass::callStaticMethod<jint[]>("staticIntArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+ QCOMPARE(array.asContainer(), (QList<jint>{3, 2, 1}));
+
+ QJniArray<jint> newArray(QList<jint>{3, 2, 1});
+ QVERIFY(newArray.isValid());
+ const auto reverse = TestClass::callStaticMethod<jint[]>("staticReverseIntArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.asContainer(), (QList<jint>{1, 2, 3}));
}
{
@@ -1593,6 +1702,14 @@ void tst_QJniObject::templateApiCheck()
const auto array = testClass.callMethod<jint[]>("intArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+ QCOMPARE(array.asContainer(), (QList<jint>{3, 2, 1}));
+
+ QJniArray<jint> newArray = QJniArrayBase::fromContainer(QList<jint>{3, 2, 1});
+ QVERIFY(newArray.isValid());
+ const auto reverse = testClass.callMethod<jint[]>("reverseIntArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.asContainer(), (QList<jint>{1, 2, 3}));
}
// jlongArray ---------------------------------------------------------------------------------
@@ -1603,6 +1720,14 @@ void tst_QJniObject::templateApiCheck()
const auto array = TestClass::callStaticMethod<jlong[]>("staticLongArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+ QCOMPARE(array.asContainer(), (QList<jlong>{3, 2, 1}));
+
+ QJniArray<jlong> newArray(QList<jlong>{3, 2, 1});
+ QVERIFY(newArray.isValid());
+ const auto reverse = TestClass::callStaticMethod<jlong[]>("staticReverseLongArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.asContainer(), (QList<jlong>{1, 2, 3}));
}
{
@@ -1611,6 +1736,14 @@ void tst_QJniObject::templateApiCheck()
const auto array = testClass.callMethod<jlong[]>("longArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+ QCOMPARE(array.asContainer(), (QList<jlong>{3, 2, 1}));
+
+ QJniArray<jlong> newArray = QJniArrayBase::fromContainer(QList<jlong>{3, 2, 1});
+ QVERIFY(newArray.isValid());
+ const auto reverse = testClass.callMethod<jlong[]>("reverseLongArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.asContainer(), (QList<jlong>{1, 2, 3}));
}
// jfloatArray --------------------------------------------------------------------------------
@@ -1621,6 +1754,14 @@ void tst_QJniObject::templateApiCheck()
const auto array = TestClass::callStaticMethod<jfloat[]>("staticFloatArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+ QCOMPARE(array.asContainer(), (QList<jfloat>{1.0f, 2.0f, 3.0f}));
+
+ QJniArray<jfloat> newArray(QList<jfloat>{3.0f, 2.0f, 1.0f});
+ QVERIFY(newArray.isValid());
+ const auto reverse = TestClass::callStaticMethod<jfloat[]>("staticReverseFloatArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.asContainer(), (QList<jfloat>{1.0f, 2.0f, 3.0f}));
}
{
@@ -1629,6 +1770,14 @@ void tst_QJniObject::templateApiCheck()
const auto array = testClass.callMethod<jfloat[]>("floatArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+ QCOMPARE(array.asContainer(), (QList<jfloat>{1.0f, 2.0f, 3.0f}));
+
+ QJniArray<jfloat> newArray = QJniArrayBase::fromContainer(QList<jfloat>{3.0f, 2.0f, 1.0f});
+ QVERIFY(newArray.isValid());
+ const auto reverse = testClass.callMethod<jfloat[]>("reverseFloatArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.asContainer(), (QList<jfloat>{1.0f, 2.0f, 3.0f}));
}
// jdoubleArray -------------------------------------------------------------------------------
@@ -1639,6 +1788,14 @@ void tst_QJniObject::templateApiCheck()
const auto array = TestClass::callStaticMethod<jdouble[]>("staticDoubleArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+ QCOMPARE(array.asContainer(), (QList<jdouble>{3.0, 2.0, 1.0}));
+
+ QJniArray<jdouble> newArray(QList<jdouble>{3.0, 2.0, 1.0});
+ QVERIFY(newArray.isValid());
+ const auto reverse = TestClass::callStaticMethod<jdouble[]>("staticReverseDoubleArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.asContainer(), (QList<jdouble>{1.0, 2.0, 3.0}));
}
{
@@ -1647,6 +1804,14 @@ void tst_QJniObject::templateApiCheck()
const auto array = testClass.callMethod<jdouble[]>("doubleArrayMethod");
QVERIFY(array.isValid());
+ QCOMPARE(array.size(), 3);
+ QCOMPARE(array.asContainer(), (QList<jdouble>{3.0, 2.0, 1.0}));
+
+ QJniArray<jdouble> newArray = QJniArrayBase::fromContainer(QList<jdouble>{3.0, 2.0, 1.0});
+ QVERIFY(newArray.isValid());
+ const auto reverse = testClass.callMethod<jdouble[]>("reverseDoubleArray", newArray);
+ QVERIFY(reverse.isValid());
+ QCOMPARE(reverse.asContainer(), (QList<jdouble>{1.0, 2.0, 3.0}));
}
}
diff --git a/tests/auto/corelib/kernel/qjnitypes/tst_qjnitypes.cpp b/tests/auto/corelib/kernel/qjnitypes/tst_qjnitypes.cpp
index a499b6f2d2..f9d9a4c13c 100644
--- a/tests/auto/corelib/kernel/qjnitypes/tst_qjnitypes.cpp
+++ b/tests/auto/corelib/kernel/qjnitypes/tst_qjnitypes.cpp
@@ -4,6 +4,7 @@
#include <QtTest>
#include <QtCore/qjnitypes.h>
+#include <QtCore/qjniarray.h>
using namespace Qt::StringLiterals;
@@ -59,8 +60,7 @@ static_assert(!(QtJniTypes::Traits<QtJavaWrapper>::signature() == "X"));
Q_DECLARE_JNI_CLASS(JavaType, "org/qtproject/qt/JavaType");
static_assert(QtJniTypes::Traits<QtJniTypes::JavaType>::signature() == "Lorg/qtproject/qt/JavaType;");
-Q_DECLARE_JNI_TYPE(ArrayType, "[Lorg/qtproject/qt/ArrayType;")
-static_assert(QtJniTypes::Traits<QtJniTypes::ArrayType>::signature() == "[Lorg/qtproject/qt/ArrayType;");
+static_assert(QtJniTypes::Traits<QtJniTypes::JavaType[]>::signature() == "[Lorg/qtproject/qt/JavaType;");
Q_DECLARE_JNI_CLASS(String, "java/lang/String");
static_assert(QtJniTypes::Traits<jstring>::className() == "java/lang/String");
@@ -119,6 +119,10 @@ static_assert(!QtJniTypes::CTString("ABCDE").startsWith("9AB"));
static_assert(QtJniTypes::CTString("ABCDE").startsWith('A'));
static_assert(!QtJniTypes::CTString("ABCDE").startsWith('B'));
+static_assert(QtJniTypes::Traits<QJniArray<jobject>>::signature() == "[Ljava/lang/Object;");
+static_assert(QtJniTypes::Traits<QJniArray<jbyte>>::signature() == "[B");
+static_assert(QtJniTypes::isObjectType<QJniArray<jbyte>>());
+
static_assert(QtJniTypes::CTString("ABCDE").endsWith("CDE"));
static_assert(QtJniTypes::CTString("ABCDE").endsWith("E"));
static_assert(QtJniTypes::CTString("ABCDE").endsWith("ABCDE"));