JNI: use conversion function from Traits in QJniArray
Remove the special handling for various object-types, use the Traits specialization instead when the type we want is an object type. Change-Id: Ia7f3c3a11b5687d2fb8a6c3ab0cea15963dacea5 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
This commit is contained in:
parent
5342046ff8
commit
129b914051
@ -573,8 +573,7 @@ protected:
|
|||||||
std::is_same<ElementType, QString>,
|
std::is_same<ElementType, QString>,
|
||||||
std::is_base_of<QtJniTypes::JObjectBase, ElementType>
|
std::is_base_of<QtJniTypes::JObjectBase, ElementType>
|
||||||
>) {
|
>) {
|
||||||
using ResultType = decltype(std::declval<QtJniTypes::Detail::LocalFrame<void>>()
|
using ResultType = decltype(QtJniTypes::Traits<ElementType>::convertToJni(nullptr, {}));
|
||||||
.convertToJni(std::declval<ElementType>()));
|
|
||||||
const auto className = QtJniTypes::Traits<ResultType>::className();
|
const auto className = QtJniTypes::Traits<ResultType>::className();
|
||||||
jclass elementClass = env.findClass(className);
|
jclass elementClass = env.findClass(className);
|
||||||
if (!elementClass) {
|
if (!elementClass) {
|
||||||
@ -694,9 +693,7 @@ public:
|
|||||||
|
|
||||||
auto arrayObject() const
|
auto arrayObject() const
|
||||||
{
|
{
|
||||||
if constexpr (std::is_convertible_v<jobject, T>)
|
if constexpr (QtJniTypes::isObjectType<T>())
|
||||||
return object<jobjectArray>();
|
|
||||||
else if constexpr (std::is_same_v<T, QString>)
|
|
||||||
return object<jobjectArray>();
|
return object<jobjectArray>();
|
||||||
else if constexpr (QtJniTypes::sameTypeForJni<T, jbyte>)
|
else if constexpr (QtJniTypes::sameTypeForJni<T, jbyte>)
|
||||||
return object<jbyteArray>();
|
return object<jbyteArray>();
|
||||||
@ -741,26 +738,12 @@ public:
|
|||||||
const_reference at(size_type i) const
|
const_reference at(size_type i) const
|
||||||
{
|
{
|
||||||
JNIEnv *env = jniEnv();
|
JNIEnv *env = jniEnv();
|
||||||
if constexpr (std::is_convertible_v<jobject, T>) {
|
if constexpr (QtJniTypes::isObjectType<T>()) {
|
||||||
jobject element = env->GetObjectArrayElement(object<jobjectArray>(), i);
|
jobject element = env->GetObjectArrayElement(object<jobjectArray>(), i);
|
||||||
if constexpr (std::is_base_of_v<QJniObject, T>)
|
if constexpr (std::is_base_of_v<std::remove_pointer_t<jobject>, std::remove_pointer_t<T>>)
|
||||||
return QJniObject::fromLocalRef(element);
|
return static_cast<T>(element);
|
||||||
else if constexpr (std::is_base_of_v<QtJniTypes::JObjectBase, T>)
|
|
||||||
return T::fromLocalRef(element);
|
|
||||||
else
|
else
|
||||||
return T{element};
|
return QtJniTypes::Traits<T>::convertFromJni(QJniObject::fromLocalRef(element));
|
||||||
} else if constexpr (std::is_same_v<QString, T>) {
|
|
||||||
jstring string = static_cast<jstring>(env->GetObjectArrayElement(arrayObject(), i));
|
|
||||||
if (string) {
|
|
||||||
QString res = QtJniTypes::Detail::toQString(string, env);
|
|
||||||
env->DeleteLocalRef(string);
|
|
||||||
return res;
|
|
||||||
} else {
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
} 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 {
|
} else {
|
||||||
T res = {};
|
T res = {};
|
||||||
if constexpr (QtJniTypes::sameTypeForJni<T, jbyte>)
|
if constexpr (QtJniTypes::sameTypeForJni<T, jbyte>)
|
||||||
@ -787,15 +770,10 @@ public:
|
|||||||
{
|
{
|
||||||
JNIEnv *env = jniEnv();
|
JNIEnv *env = jniEnv();
|
||||||
|
|
||||||
if constexpr (std::disjunction_v<std::is_base_of<QtJniTypes::JObjectBase, T>,
|
if constexpr (QtJniTypes::isObjectType<T>()) {
|
||||||
std::is_same<QJniObject, T>>) {
|
QtJniTypes::Detail::LocalFrame<T> frame(env);
|
||||||
env->SetObjectArrayElement(object<jobjectArray>(), i, val.object());
|
jobject element = frame.template convertToJni(val);
|
||||||
} else if constexpr (std::is_same_v<QString, T>) {
|
env->SetObjectArrayElement(object<jobjectArray>(), i, element);
|
||||||
env->SetObjectArrayElement(object<jobjectArray>(), i,
|
|
||||||
QJniObject::fromString(val).template object<jstring>());
|
|
||||||
} else if constexpr (std::is_base_of_v<std::remove_pointer_t<jobject>, std::remove_pointer_t<T>>) {
|
|
||||||
// jstring, jclass etc
|
|
||||||
env->SetObjectArrayElement(object<jobjectArray>(), i, val);
|
|
||||||
} else { // primitive types
|
} else { // primitive types
|
||||||
if constexpr (QtJniTypes::sameTypeForJni<T, jbyte>)
|
if constexpr (QtJniTypes::sameTypeForJni<T, jbyte>)
|
||||||
env->SetByteArrayRegion(object<jbyteArray>(), i, 1, &val);
|
env->SetByteArrayRegion(object<jbyteArray>(), i, 1, &val);
|
||||||
@ -918,8 +896,8 @@ template <typename List>
|
|||||||
auto QJniArrayBase::makeObjectArray(List &&list)
|
auto QJniArrayBase::makeObjectArray(List &&list)
|
||||||
{
|
{
|
||||||
using ElementType = typename q20::remove_cvref_t<List>::value_type;
|
using ElementType = typename q20::remove_cvref_t<List>::value_type;
|
||||||
using ResultType = QJniArray<decltype(std::declval<QtJniTypes::Detail::LocalFrame<>>()
|
using ResultType = QJniArray<decltype(QtJniTypes::Traits<ElementType>::convertToJni(nullptr,
|
||||||
.convertToJni(std::declval<ElementType>()))>;
|
{}))>;
|
||||||
|
|
||||||
if (std::size(list) == 0)
|
if (std::size(list) == 0)
|
||||||
return ResultType();
|
return ResultType();
|
||||||
@ -945,8 +923,6 @@ auto QJniArrayBase::makeObjectArray(List &&list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// explicitly manage the frame for local references in chunks of 100
|
// explicitly manage the frame for local references in chunks of 100
|
||||||
QtJniTypes::Detail::LocalFrame frame(env);
|
|
||||||
frame.hasFrame = true;
|
|
||||||
constexpr jint frameCapacity = 100;
|
constexpr jint frameCapacity = 100;
|
||||||
qsizetype i = 0;
|
qsizetype i = 0;
|
||||||
for (const auto &element : std::as_const(list)) {
|
for (const auto &element : std::as_const(list)) {
|
||||||
@ -956,13 +932,12 @@ auto QJniArrayBase::makeObjectArray(List &&list)
|
|||||||
if (env->PushLocalFrame(frameCapacity) != 0)
|
if (env->PushLocalFrame(frameCapacity) != 0)
|
||||||
return ResultType{};
|
return ResultType{};
|
||||||
}
|
}
|
||||||
jobject object = frame.convertToJni(element);
|
jobject object = QtJniTypes::Traits<ElementType>::convertToJni(env, element);
|
||||||
env->SetObjectArrayElement(localArray, i, object);
|
env->SetObjectArrayElement(localArray, i, object);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
if (i)
|
if (i)
|
||||||
env->PopLocalFrame(nullptr);
|
env->PopLocalFrame(nullptr);
|
||||||
frame.hasFrame = false;
|
|
||||||
return ResultType(QJniObject::fromLocalRef(localArray));
|
return ResultType(QJniObject::fromLocalRef(localArray));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,6 +148,13 @@ void tst_QJniArray::construct()
|
|||||||
QCOMPARE(list.at(500), QString::number(500));
|
QCOMPARE(list.at(500), QString::number(500));
|
||||||
QCOMPARE(list.toContainer(), strings);
|
QCOMPARE(list.toContainer(), strings);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
constexpr qsizetype size = 5;
|
||||||
|
const QJniArray<jstring> list(size);
|
||||||
|
const QStringList strings = list.toContainer();
|
||||||
|
QCOMPARE(strings.at(0), QString());
|
||||||
|
QCOMPARE(strings.size(), size);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
QJniArray bytes = QJniArrayBase::fromContainer(QByteArray("abc"));
|
QJniArray bytes = QJniArrayBase::fromContainer(QByteArray("abc"));
|
||||||
static_assert(std::is_same_v<decltype(bytes)::value_type, jbyte>);
|
static_assert(std::is_same_v<decltype(bytes)::value_type, jbyte>);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user