summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qjniarray.h44
-rw-r--r--src/corelib/kernel/qjniobject.h2
2 files changed, 37 insertions, 9 deletions
diff --git a/src/corelib/kernel/qjniarray.h b/src/corelib/kernel/qjniarray.h
index f2f4dba92e..862bd71baf 100644
--- a/src/corelib/kernel/qjniarray.h
+++ b/src/corelib/kernel/qjniarray.h
@@ -127,6 +127,7 @@ public:
using ElementType = typename std::remove_reference_t<Container>::value_type;
if constexpr (std::disjunction_v<std::is_same<ElementType, jobject>,
std::is_same<ElementType, QJniObject>,
+ std::is_same<ElementType, QString>,
std::is_base_of<QtJniTypes::JObjectBase, ElementType>
>) {
return makeObjectArray(std::forward<Container>(container));
@@ -275,6 +276,9 @@ public:
return T::fromLocalRef(element);
else
return T{element};
+ } else if constexpr (std::is_base_of_v<std::remove_pointer_t<jobject>, std::remove_pointer_t<T>>) {
+ // jstring, jclass etc
+ return static_cast<T>(env->GetObjectArrayElement(object<jobjectArray>(), i));
} else {
T res = {};
if constexpr (std::is_same_v<T, jbyte>)
@@ -305,6 +309,12 @@ public:
for (auto element : *this)
res.append(element);
return res;
+ } else if constexpr (std::is_same_v<T, jstring>) {
+ QStringList res;
+ res.reserve(size());
+ for (auto element : *this)
+ res.append(QJniObject(element).toString());
+ return res;
} else if constexpr (std::is_same_v<T, jbyte>) {
const qsizetype bytecount = size();
QByteArray res(bytecount, Qt::Initialization::Uninitialized);
@@ -364,8 +374,12 @@ template <typename List>
auto QJniArrayBase::makeObjectArray(List &&list)
{
using ElementType = typename q20::remove_cvref_t<List>::value_type;
+ using ResultType = QJniArray<decltype(std::declval<QJniObject::LocalFrame<>>().convertToJni(
+ std::declval<ElementType>()))
+ >;
+
if (list.isEmpty())
- return QJniArray<jobject>();
+ return ResultType();
JNIEnv *env = QJniEnvironment::getJniEnv();
const size_type length = size_type(list.size());
@@ -375,21 +389,33 @@ auto QJniArrayBase::makeObjectArray(List &&list)
if constexpr (std::disjunction_v<std::is_same<ElementType, QJniObject>,
std::is_base_of<QtJniTypes::JObjectBase, ElementType>>) {
elementClass = list.first().objectClass();
+ } else if constexpr (std::is_same_v<ElementType, QString>) {
+ elementClass = env->FindClass("java/lang/String");
} else {
elementClass = env->GetObjectClass(list.first());
}
auto localArray = env->NewObjectArray(length, elementClass, nullptr);
if (QJniEnvironment::checkAndClearExceptions(env))
- return QJniArray<jobject>();
- for (size_type 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);
+ return ResultType();
+
+ // explicitly manage the frame for local references in chunks of 100
+ QJniObject::LocalFrame frame(env);
+ constexpr jint frameCapacity = 100;
+ qsizetype i = 0;
+ for (const auto &element : std::as_const(list)) {
+ if (i % frameCapacity == 0) {
+ if (i)
+ env->PopLocalFrame(nullptr);
+ if (env->PushLocalFrame(frameCapacity) != 0)
+ return ResultType{};
+ }
+ jobject object = frame.convertToJni(element);
env->SetObjectArrayElement(localArray, i, object);
+ ++i;
}
- return QJniArray<jobject>(localArray);
+ if (i)
+ env->PopLocalFrame(nullptr);
+ return ResultType(localArray);
}
diff --git a/src/corelib/kernel/qjniobject.h b/src/corelib/kernel/qjniobject.h
index 178a4b7faa..7c6eefc082 100644
--- a/src/corelib/kernel/qjniobject.h
+++ b/src/corelib/kernel/qjniobject.h
@@ -16,6 +16,8 @@ class QJniObjectPrivate;
class Q_CORE_EXPORT QJniObject
{
+ friend class QJniArrayBase;
+
template <typename ...Args>
struct LocalFrame {
mutable JNIEnv *env;