summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qjniobject.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qjniobject.h')
-rw-r--r--src/corelib/kernel/qjniobject.h1175
1 files changed, 629 insertions, 546 deletions
diff --git a/src/corelib/kernel/qjniobject.h b/src/corelib/kernel/qjniobject.h
index 80568b2970..589f6489f7 100644
--- a/src/corelib/kernel/qjniobject.h
+++ b/src/corelib/kernel/qjniobject.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 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 QJNIOBJECT_H
#define QJNIOBJECT_H
@@ -52,313 +16,391 @@ class QJniObjectPrivate;
class Q_CORE_EXPORT QJniObject
{
+ friend class QJniArrayBase;
+
+ template <typename ...Args>
+ struct LocalFrame {
+ mutable JNIEnv *env;
+ bool hasFrame = false;
+ explicit LocalFrame(JNIEnv *env = nullptr) noexcept
+ : env(env)
+ {
+ }
+ ~LocalFrame()
+ {
+ if (hasFrame)
+ env->PopLocalFrame(nullptr);
+ }
+ template <typename T>
+ auto newLocalRef(jobject object)
+ {
+ if (!hasFrame) {
+ if (jniEnv()->PushLocalFrame(sizeof...(Args)) < 0)
+ return T{}; // JVM is out of memory, avoid making matters worse
+ hasFrame = true;
+ }
+ return static_cast<T>(jniEnv()->NewLocalRef(object));
+ }
+ template <typename T>
+ auto newLocalRef(const QJniObject &object)
+ {
+ return newLocalRef<T>(object.template object<T>());
+ }
+ JNIEnv *jniEnv() const
+ {
+ if (!env)
+ env = QJniEnvironment::getJniEnv();
+ return env;
+ }
+ bool checkAndClearExceptions()
+ {
+ return env ? QJniEnvironment::checkAndClearExceptions(env) : false;
+ }
+ template <typename T>
+ auto convertToJni(T &&value);
+ template <typename T>
+ auto convertFromJni(QJniObject &&object);
+ };
public:
QJniObject();
explicit QJniObject(const char *className);
explicit QJniObject(const char *className, const char *signature, ...);
- explicit QJniObject(jclass clazz);
- explicit QJniObject(jclass clazz, const char *signature, ...);
- QJniObject(jobject globalRef);
- ~QJniObject();
-
- jobject object() const;
- template <typename T> T object() const
+ template<typename ...Args
+#ifndef Q_QDOC
+ , std::enable_if_t<!std::disjunction_v<QtJniTypes::IsStringType<std::decay_t<Args>>...>>* = nullptr
+#endif
+ >
+ explicit QJniObject(const char *className, Args &&...args)
+ : QJniObject(LocalFrame<Args...>{}, className, std::forward<Args>(args)...)
{
- assertJniObjectType<T>();
- return static_cast<T>(javaObject());
}
-
- jclass objectClass() const;
- QByteArray className() const;
-
- template <typename T>
- T callMethod(const char *methodName, const char *signature, ...) const
+private:
+ template<typename ...Args>
+ explicit QJniObject(LocalFrame<Args...> localFrame, const char *className, Args &&...args)
+ : QJniObject(className, QtJniTypes::constructorSignature<Args...>().data(),
+ localFrame.convertToJni(std::forward<Args>(args))...)
{
- assertJniPrimitiveType<T>();
- QJniEnvironment env;
- T res{};
- jmethodID id = getCachedMethodID(env.jniEnv(), methodName, signature);
- if (id) {
- va_list args;
- va_start(args, signature);
- callMethodForType<T>(env.jniEnv(), res, object(), id, args);
- va_end(args);
- if (env.checkAndClearExceptions())
- res = {};
- }
- return res;
}
+public:
+ explicit QJniObject(jclass clazz);
+ explicit QJniObject(jclass clazz, const char *signature, ...);
+ template<typename ...Args
+#ifndef Q_QDOC
+ , std::enable_if_t<!std::disjunction_v<QtJniTypes::IsStringType<std::decay_t<Args>>...>>* = nullptr
+#endif
+ >
+ explicit QJniObject(jclass clazz, Args &&...args)
+ : QJniObject(clazz, QtJniTypes::constructorSignature<Args...>().data(),
+ std::forward<Args>(args)...)
+ {}
+ QJniObject(jobject globalRef);
- template <>
- void callMethod<void>(const char *methodName, const char *signature, ...) const
- {
- QJniEnvironment env;
- jmethodID id = getCachedMethodID(env.jniEnv(), methodName, signature);
- if (id) {
- va_list args;
- va_start(args, signature);
- callVoidMethodV(env.jniEnv(), id, args);
- va_end(args);
- env.checkAndClearExceptions();
- }
- }
+ QJniObject(const QJniObject &other) noexcept = default;
+ QJniObject(QJniObject &&other) noexcept = default;
+ QJniObject &operator=(const QJniObject &other) noexcept = default;
+ QJniObject &operator=(QJniObject &&other) noexcept = default;
- template <typename T>
- T callMethod(const char *methodName) const
- {
- assertJniPrimitiveType<T>();
- constexpr const char *signature = getTypeSignature<T>();
- return callMethod<T>(methodName, QByteArray(signature).prepend("()").constData());
- }
+ ~QJniObject();
- template <>
- void callMethod<void>(const char *methodName) const
+ template<typename Class, typename ...Args>
+ static inline QJniObject construct(Args &&...args)
{
- callMethod<void>(methodName, "()V");
+ LocalFrame<Args...> frame;
+ return QJniObject(QtJniTypes::Traits<Class>::className().data(),
+ QtJniTypes::constructorSignature<Args...>().data(),
+ frame.convertToJni(std::forward<Args>(args))...);
}
- template <typename T>
- QJniObject callObjectMethod(const char *methodName) const
+ jobject object() const;
+ template <typename T> T object() const
{
- assertJniObjectType<T>();
- constexpr const char *signature = getTypeSignature<T>();
- return callObjectMethod(methodName, QByteArray(signature).prepend("()").constData());
+ QtJniTypes::assertObjectType<T>();
+ return static_cast<T>(javaObject());
}
- QJniObject callObjectMethod(const char *methodName, const char *signature, ...) const;
-
- template <typename T>
- static T callStaticMethod(const char *className, const char *methodName,
- const char *signature, ...)
- {
- assertJniPrimitiveType<T>();
- QJniEnvironment env;
- T res{};
- jclass clazz = QJniObject::loadClass(className, env.jniEnv());
- if (clazz) {
- jmethodID id = getCachedMethodID(env.jniEnv(), clazz,
- QJniObject::toBinaryEncClassName(className),
- methodName, signature, true);
- if (id) {
- va_list args;
- va_start(args, signature);
- callStaticMethodForType<T>(env.jniEnv(), res, clazz, id, args);
- va_end(args);
- if (env.checkAndClearExceptions())
- res = {};
- }
- }
- return res;
- }
+ jclass objectClass() const;
+ QByteArray className() const;
- template <>
- void callStaticMethod<void>(const char *className, const char *methodName,
- const char *signature, ...)
- {
- QJniEnvironment env;
- jclass clazz = QJniObject::loadClass(className, env.jniEnv());
- if (clazz) {
- jmethodID id = getCachedMethodID(env.jniEnv(), clazz,
- QJniObject::toBinaryEncClassName(className),
- methodName, signature, true);
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<Ret> = true
+#endif
+ >
+ auto callMethod(const char *methodName, const char *signature, Args &&...args) const
+ {
+ LocalFrame<Args...> frame(jniEnv());
+ if constexpr (QtJniTypes::isObjectType<Ret>()) {
+ return frame.template convertFromJni<Ret>(callObjectMethod(methodName, signature,
+ frame.convertToJni(std::forward<Args>(args))...));
+ } else {
+ jmethodID id = getCachedMethodID(frame.jniEnv(), methodName, signature);
if (id) {
- va_list args;
- va_start(args, signature);
- env->CallStaticVoidMethodV(clazz, id, args);
- va_end(args);
- env.checkAndClearExceptions();
+ if constexpr (std::is_same_v<Ret, void>) {
+ callVoidMethodV(frame.jniEnv(), id,
+ frame.convertToJni(std::forward<Args>(args))...);
+ frame.checkAndClearExceptions();
+ } else {
+ Ret res{};
+ callMethodForType<Ret>(frame.jniEnv(), res, object(), id,
+ frame.convertToJni(std::forward<Args>(args))...);
+ if (frame.checkAndClearExceptions())
+ res = {};
+ return res;
+ }
}
+ if constexpr (!std::is_same_v<Ret, void>)
+ return Ret{};
}
}
- template <typename T>
- static T callStaticMethod(const char *className, const char *methodName)
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ auto callMethod(const char *methodName, Args &&...args) const
{
- assertJniPrimitiveType<T>();
- constexpr const char *signature = getTypeSignature<T>();
- return callStaticMethod<T>(className, methodName, QByteArray(signature).prepend("()").constData());
+ constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
+ return callMethod<Ret>(methodName, signature.data(), std::forward<Args>(args)...);
}
- template <>
- void callStaticMethod<void>(const char *className, const char *methodName)
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ QJniObject callObjectMethod(const char *methodName, Args &&...args) const
{
- callStaticMethod<void>(className, methodName, "()V");
+ QtJniTypes::assertObjectType<Ret>();
+ constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
+ LocalFrame<Args...> frame(jniEnv());
+ return frame.template convertFromJni<Ret>(callObjectMethod(methodName, signature,
+ frame.convertToJni(std::forward<Args>(args))...));
}
- template <typename T>
- static T callStaticMethod(jclass clazz, const char *methodName, const char *signature, ...)
- {
- assertJniPrimitiveType<T>();
- QJniEnvironment env;
- T res{};
- if (clazz) {
- jmethodID id = getMethodID(env.jniEnv(), clazz, methodName, signature, true);
- if (id) {
- va_list args;
- va_start(args, signature);
- callStaticMethodForType<T>(env.jniEnv(), res, clazz, id, args);
- va_end(args);
- if (env.checkAndClearExceptions())
- res = {};
- }
- }
- return res;
- }
+ QJniObject callObjectMethod(const char *methodName, const char *signature, ...) const;
- template <>
- void callStaticMethod<void>(jclass clazz, const char *methodName,
- const char *signature, ...)
+ template <typename Ret, typename ...Args>
+ static auto callStaticMethod(const char *className, const char *methodName, const char *signature, Args &&...args)
{
- QJniEnvironment env;
- if (clazz) {
- jmethodID id = getMethodID(env.jniEnv(), clazz, methodName, signature, true);
- if (id) {
- va_list args;
- va_start(args, signature);
- env->CallStaticVoidMethodV(clazz, id, args);
- va_end(args);
- env.checkAndClearExceptions();
- }
- }
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ jclass clazz = QJniObject::loadClass(className, env);
+ return callStaticMethod<Ret>(clazz, methodName, signature, std::forward<Args>(args)...);
}
- template <typename T>
- static T callStaticMethod(jclass clazz, jmethodID methodId, ...)
+ template <typename Ret, typename ...Args>
+ static auto callStaticMethod(jclass clazz, const char *methodName, const char *signature, Args &&...args)
{
- assertJniPrimitiveType<T>();
- QJniEnvironment env;
- T res{};
- if (clazz && methodId) {
- va_list args;
- va_start(args, methodId);
- callStaticMethodForType<T>(env.jniEnv(), res, clazz, methodId, args);
- va_end(args);
- if (env.checkAndClearExceptions())
- res = {};
- }
- return res;
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ jmethodID id = clazz ? getMethodID(env, clazz, methodName, signature, true)
+ : 0;
+ return callStaticMethod<Ret>(clazz, id, std::forward<Args>(args)...);
}
- template <>
- void callStaticMethod<void>(jclass clazz, jmethodID methodId, ...)
- {
- QJniEnvironment env;
- if (clazz && methodId) {
- va_list args;
- va_start(args, methodId);
- env->CallStaticVoidMethodV(clazz, methodId, args);
- va_end(args);
- env.checkAndClearExceptions();
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<Ret> = true
+#endif
+ >
+ static auto callStaticMethod(jclass clazz, jmethodID methodId, Args &&...args)
+ {
+ LocalFrame<Args...> frame;
+ if constexpr (QtJniTypes::isObjectType<Ret>()) {
+ return frame.template convertFromJni<Ret>(callStaticObjectMethod(clazz, methodId,
+ frame.convertToJni(std::forward<Args>(args))...));
+ } else {
+ if (clazz && methodId) {
+ if constexpr (std::is_same_v<Ret, void>) {
+ callStaticMethodForVoid(frame.jniEnv(), clazz, methodId,
+ frame.convertToJni(std::forward<Args>(args))...);
+ frame.checkAndClearExceptions();
+ } else {
+ Ret res{};
+ callStaticMethodForType<Ret>(frame.jniEnv(), res, clazz, methodId,
+ frame.convertToJni(std::forward<Args>(args))...);
+ if (frame.checkAndClearExceptions())
+ res = {};
+ return res;
+ }
+ }
+ if constexpr (!std::is_same_v<Ret, void>)
+ return Ret{};
}
}
- template <typename T> static T callStaticMethod(jclass clazz, const char *methodName)
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ static auto callStaticMethod(const char *className, const char *methodName, Args &&...args)
{
- assertJniPrimitiveType<T>();
- constexpr const char *signature = getTypeSignature<T>();
- return callStaticMethod<T>(clazz, methodName, QByteArray(signature).prepend("()").constData());
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ jclass clazz = QJniObject::loadClass(className, env);
+ const jmethodID id = clazz ? getMethodID(env, clazz, methodName,
+ QtJniTypes::methodSignature<Ret, Args...>().data(), true)
+ : 0;
+ return callStaticMethod<Ret>(clazz, id, std::forward<Args>(args)...);
}
- template <>
- void callStaticMethod<void>(jclass clazz, const char *methodName)
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ static auto callStaticMethod(jclass clazz, const char *methodName, Args &&...args)
{
- callStaticMethod<void>(clazz, methodName, "()V");
+ constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
+ return callStaticMethod<Ret>(clazz, methodName, signature.data(), std::forward<Args>(args)...);
}
-
- template <typename T>
- static QJniObject callStaticObjectMethod(const char *className, const char *methodName)
+ template <typename Klass, typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ static auto callStaticMethod(const char *methodName, Args &&...args)
{
- assertJniObjectType<T>();
- constexpr const char *signature = getTypeSignature<T>();
- return callStaticObjectMethod(className, methodName, QByteArray(signature).prepend("()").constData());
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ const jclass clazz = QJniObject::loadClass(QtJniTypes::Traits<Klass>::className().data(),
+ env);
+ const jmethodID id = clazz ? getMethodID(env, clazz, methodName,
+ QtJniTypes::methodSignature<Ret, Args...>().data(), true)
+ : 0;
+ return callStaticMethod<Ret>(clazz, id, std::forward<Args>(args)...);
}
static QJniObject callStaticObjectMethod(const char *className, const char *methodName,
const char *signature, ...);
- template <typename T>
- static QJniObject callStaticObjectMethod(jclass clazz, const char *methodName)
- {
- assertJniObjectType<T>();
- constexpr const char *signature = getTypeSignature<T>();
- return callStaticObjectMethod(clazz, methodName, QByteArray(signature).prepend("()").constData());
- }
-
static QJniObject callStaticObjectMethod(jclass clazz, const char *methodName,
const char *signature, ...);
static QJniObject callStaticObjectMethod(jclass clazz, jmethodID methodId, ...);
- template <typename T> T getField(const char *fieldName) const
+
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ static QJniObject callStaticObjectMethod(const char *className, const char *methodName, Args &&...args)
{
- assertJniPrimitiveType<T>();
- QJniEnvironment env;
- T res{};
- constexpr const char *signature = getTypeSignature<T>();
- jfieldID id = getCachedFieldID(env.jniEnv(), fieldName, signature);
- if (id) {
- getFieldForType<T>(env.jniEnv(), res, object(), id);
- if (env.checkAndClearExceptions())
- res = {};
- }
- return res;
+ QtJniTypes::assertObjectType<Ret>();
+ constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
+ LocalFrame<Args...> frame;
+ return frame.template convertFromJni<Ret>(callStaticObjectMethod(className, methodName, signature.data(),
+ frame.convertToJni(std::forward<Args>(args))...));
}
- template <typename T>
- static T getStaticField(const char *className, const char *fieldName)
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ static QJniObject callStaticObjectMethod(jclass clazz, const char *methodName, Args &&...args)
{
- assertJniPrimitiveType<T>();
- QJniEnvironment env;
- jclass clazz = QJniObject::loadClass(className, env.jniEnv());
- if (!clazz)
- return 0;
+ QtJniTypes::assertObjectType<Ret>();
+ constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
+ LocalFrame<Args...> frame;
+ return frame.template convertFromJni<Ret>(callStaticObjectMethod(clazz, methodName, signature.data(),
+ frame.convertToJni(std::forward<Args>(args))...));
+ }
- constexpr const char *signature = getTypeSignature<T>();
- jfieldID id = getCachedFieldID(env.jniEnv(), clazz,
- QJniObject::toBinaryEncClassName(className),
- fieldName,
- signature, true);
- if (!id)
- return 0;
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ auto getField(const char *fieldName) const
+ {
+ LocalFrame<T> frame(jniEnv());
+ if constexpr (QtJniTypes::isObjectType<T>()) {
+ return frame.template convertFromJni<T>(getObjectField<T>(fieldName));
+ } else {
+ T res{};
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
+ jfieldID id = getCachedFieldID(frame.jniEnv(), fieldName, signature);
+ if (id) {
+ getFieldForType<T>(frame.jniEnv(), res, object(), id);
+ if (frame.checkAndClearExceptions())
+ res = {};
+ }
+ return res;
+ }
+ }
- T res{};
- getStaticFieldForType<T>(env.jniEnv(), res, clazz, id);
- if (env.checkAndClearExceptions())
- res = {};
- return res;
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ static auto getStaticField(const char *className, const char *fieldName)
+ {
+ LocalFrame<T> frame;
+ if constexpr (QtJniTypes::isObjectType<T>()) {
+ return frame.template convertFromJni<T>(getStaticObjectField<T>(className, fieldName));
+ } else {
+ jclass clazz = QJniObject::loadClass(className, frame.jniEnv());
+ if (!clazz)
+ return T{};
+ return getStaticField<T>(clazz, fieldName);
+ }
}
- template <typename T>
- static T getStaticField(jclass clazz, const char *fieldName)
- {
- assertJniPrimitiveType<T>();
- QJniEnvironment env;
- T res{};
- constexpr const char *signature = getTypeSignature<T>();
- jfieldID id = getFieldID(env.jniEnv(), clazz, fieldName, signature, true);
- if (id) {
- getStaticFieldForType<T>(env.jniEnv(), res, clazz, id);
- if (env.checkAndClearExceptions())
- res = {};
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ static auto getStaticField(jclass clazz, const char *fieldName)
+ {
+ LocalFrame<T> frame;
+ if constexpr (QtJniTypes::isObjectType<T>()) {
+ return frame.template convertFromJni<T>(getStaticObjectField<T>(clazz, fieldName));
+ } else {
+ T res{};
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
+ jfieldID id = getFieldID(frame.jniEnv(), clazz, fieldName, signature, true);
+ if (id) {
+ getStaticFieldForType<T>(frame.jniEnv(), res, clazz, id);
+ if (frame.checkAndClearExceptions())
+ res = {};
+ }
+ return res;
}
- return res;
}
- template <typename T>
+ template <typename Klass, typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ static auto getStaticField(const char *fieldName)
+ {
+ return getStaticField<T>(QtJniTypes::Traits<Klass>::className(), fieldName);
+ }
+
+ template <typename T
+#ifndef Q_QDOC
+ , std::enable_if_t<QtJniTypes::isObjectType<T>(), bool> = true
+#endif
+ >
QJniObject getObjectField(const char *fieldName) const
{
- assertJniObjectType<T>();
- constexpr const char *signature = getTypeSignature<T>();
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
return getObjectField(fieldName, signature);
}
QJniObject getObjectField(const char *fieldName, const char *signature) const;
- template <typename T>
+ template <typename T
+#ifndef Q_QDOC
+ , std::enable_if_t<QtJniTypes::isObjectType<T>(), bool> = true
+#endif
+ >
static QJniObject getStaticObjectField(const char *className, const char *fieldName)
{
- assertJniObjectType<T>();
- constexpr const char *signature = getTypeSignature<T>();
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
return getStaticObjectField(className, fieldName, signature);
}
@@ -366,104 +408,128 @@ public:
const char *fieldName,
const char *signature);
- template <typename T>
+ template <typename T
+#ifndef Q_QDOC
+ , std::enable_if_t<QtJniTypes::isObjectType<T>(), bool> = true
+#endif
+ >
static QJniObject getStaticObjectField(jclass clazz, const char *fieldName)
{
- assertJniObjectType<T>();
- constexpr const char *signature = getTypeSignature<T>();
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
return getStaticObjectField(clazz, fieldName, signature);
}
static QJniObject getStaticObjectField(jclass clazz, const char *fieldName,
const char *signature);
- template <typename T> void setField(const char *fieldName, T value)
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ void setField(const char *fieldName, T value)
{
- assertJniType<T>();
- QJniEnvironment env;
- constexpr const char *signature = getTypeSignature<T>();
- jfieldID id = getCachedFieldID(env.jniEnv(), fieldName, signature);
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
+ jfieldID id = getCachedFieldID(jniEnv(), fieldName, signature);
if (id) {
- setFieldForType<T>(env.jniEnv(), object(), id, value);
- env.checkAndClearExceptions();
+ setFieldForType<T>(jniEnv(), object(), id, value);
+ QJniEnvironment::checkAndClearExceptions(jniEnv());
}
}
- template <typename T>
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
void setField(const char *fieldName, const char *signature, T value)
{
- assertJniType<T>();
- QJniEnvironment env;
- jfieldID id = getCachedFieldID(env.jniEnv(), fieldName, signature);
+ jfieldID id = getCachedFieldID(jniEnv(), fieldName, signature);
if (id) {
- setFieldForType<T>(env.jniEnv(), object(), id, value);
- env.checkAndClearExceptions();
+ setFieldForType<T>(jniEnv(), object(), id, value);
+ QJniEnvironment::checkAndClearExceptions(jniEnv());
}
}
- template <typename T>
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
static void setStaticField(const char *className, const char *fieldName, T value)
{
- assertJniType<T>();
- QJniEnvironment env;
- jclass clazz = QJniObject::loadClass(className, env.jniEnv());
+ LocalFrame<T> frame;
+ jclass clazz = QJniObject::loadClass(className, frame.jniEnv());
if (!clazz)
return;
- constexpr const char *signature = getTypeSignature<T>();
- jfieldID id = getCachedFieldID(env.jniEnv(), clazz, className, fieldName,
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
+ jfieldID id = getCachedFieldID(frame.jniEnv(), clazz, className, fieldName,
signature, true);
if (!id)
return;
- setStaticFieldForType<T>(env.jniEnv(), clazz, id, value);
- env.checkAndClearExceptions();
+ setStaticFieldForType<T>(frame.jniEnv(), clazz, id, value);
+ frame.checkAndClearExceptions();
}
- template <typename T>
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
static void setStaticField(const char *className, const char *fieldName,
const char *signature, T value)
{
- assertJniType<T>();
- QJniEnvironment env;
- jclass clazz = QJniObject::loadClass(className, env.jniEnv());
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ jclass clazz = QJniObject::loadClass(className, env);
if (!clazz)
return;
- jfieldID id = getCachedFieldID(env.jniEnv(), clazz, className, fieldName,
+ jfieldID id = getCachedFieldID(env, clazz, className, fieldName,
signature, true);
if (id) {
- setStaticFieldForType<T>(env.jniEnv(), clazz, id, value);
- env.checkAndClearExceptions();
+ setStaticFieldForType<T>(env, clazz, id, value);
+ QJniEnvironment::checkAndClearExceptions(env);
}
}
- template <typename T>
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
static void setStaticField(jclass clazz, const char *fieldName,
const char *signature, T value)
{
- assertJniType<T>();
- QJniEnvironment env;
- jfieldID id = getFieldID(env.jniEnv(), clazz, fieldName, signature, true);
+ JNIEnv *env = QJniEnvironment::getJniEnv();
+ jfieldID id = getFieldID(env, clazz, fieldName, signature, true);
if (id) {
- setStaticFieldForType<T>(env.jniEnv(), clazz, id, value);
- env.checkAndClearExceptions();
+ setStaticFieldForType<T>(env, clazz, id, value);
+ QJniEnvironment::checkAndClearExceptions(env);
}
}
- template <typename T>
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
static void setStaticField(jclass clazz, const char *fieldName, T value)
{
- assertJniType<T>();
- QJniEnvironment env;
- constexpr const char *signature = getTypeSignature<T>();
- jfieldID id = getFieldID(env.jniEnv(), clazz, fieldName, signature, true);
- if (id) {
- setStaticFieldForType<T>(env.jniEnv(), clazz, id, value);
- env.checkAndClearExceptions();
- }
+ setStaticField(clazz, fieldName, QtJniTypes::fieldSignature<T>(), value);
+ }
+
+ template <typename Klass, typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ static void setStaticField(const char *fieldName, T value)
+ {
+ setStaticField(QtJniTypes::Traits<Klass>::className(), fieldName, value);
}
static QJniObject fromString(const QString &string);
@@ -475,21 +541,27 @@ public:
// This function takes ownership of the jobject and releases the local ref. before returning.
static QJniObject fromLocalRef(jobject lref);
- template <typename T> QJniObject &operator=(T obj)
+ template <typename T,
+ std::enable_if_t<std::is_convertible_v<T, jobject>, bool> = true>
+ QJniObject &operator=(T obj)
{
- assertJniType<T>();
assign(static_cast<T>(obj));
return *this;
}
+protected:
+ QJniObject(Qt::Initialization) {}
+ JNIEnv *jniEnv() const noexcept;
+
private:
- struct QVaListPrivate { operator va_list &() const { return m_args; } va_list &m_args; };
- QJniObject(const char *className, const char *signature, const QVaListPrivate &args);
- QJniObject(jclass clazz, const char *signature, const QVaListPrivate &args);
+ static jclass loadClass(const QByteArray &className, JNIEnv *env);
- static jclass loadClass(const QByteArray &className, JNIEnv *env, bool binEncoded = false);
+#if QT_CORE_REMOVED_SINCE(6, 7)
+ // these need to stay in the ABI as they were used in inline methods before 6.7
+ static jclass loadClass(const QByteArray &className, JNIEnv *env, bool binEncoded);
static QByteArray toBinaryEncClassName(const QByteArray &className);
- static QJniObject getCleanJniObject(jobject obj);
+ void callVoidMethodV(JNIEnv *env, jmethodID id, va_list args) const;
+#endif
static jfieldID getCachedFieldID(JNIEnv *env, jclass clazz, const QByteArray &className,
const char *name, const char *signature,
@@ -507,15 +579,7 @@ private:
static jmethodID getMethodID(JNIEnv *env, jclass clazz, const char *name,
const char *signature, bool isStatic = false);
- void callVoidMethodV(JNIEnv *env, jmethodID id, va_list args) const;
- QJniObject callObjectMethodV(const char *methodName, const char *signature,
- va_list args) const;
-
- static QJniObject callStaticObjectMethodV(const char *className, const char *methodName,
- const char *signature, va_list args);
-
- static QJniObject callStaticObjectMethodV(jclass clazz, const char *methodName,
- const char *signature, va_list args);
+ void callVoidMethodV(JNIEnv *env, jmethodID id, ...) const;
bool isSameObject(jobject obj) const;
bool isSameObject(const QJniObject &other) const;
@@ -525,262 +589,281 @@ private:
friend bool operator==(const QJniObject &, const QJniObject &);
friend bool operator!=(const QJniObject&, const QJniObject&);
- template<bool flag = false>
- static void staticAssertTypeMismatch()
+ template<typename T>
+ static constexpr void callMethodForType(JNIEnv *env, T &res, jobject obj, jmethodID id, ...)
{
- static_assert(flag, "The used type is not supported by this template call. "
- "Use a JNI based type instead.");
+ va_list args = {};
+ va_start(args, id);
+ QtJniTypes::Caller<T>::callMethodForType(env, res, obj, id, args);
+ va_end(args);
}
template<typename T>
- static constexpr bool isJniPrimitiveType()
- {
- if constexpr(!std::is_same<T, jboolean>::value
- && !std::is_same<T, jbyte>::value
- && !std::is_same<T, jchar>::value
- && !std::is_same<T, jshort>::value
- && !std::is_same<T, jint>::value
- && !std::is_same<T, jlong>::value
- && !std::is_same<T, jfloat>::value
- && !std::is_same<T, jdouble>::value) {
- return false;
- }
+ static constexpr void callStaticMethodForType(JNIEnv *env, T &res, jclass clazz,
+ jmethodID id, ...)
+ {
+ if (!clazz || !id)
+ return;
+ va_list args = {};
+ va_start(args, id);
+ QtJniTypes::Caller<T>::callStaticMethodForType(env, res, clazz, id, args);
+ va_end(args);
+ }
- return true;
+ static void callStaticMethodForVoid(JNIEnv *env, jclass clazz, jmethodID id, ...)
+ {
+ if (!clazz || !id)
+ return;
+ va_list args;
+ va_start(args, id);
+ env->CallStaticVoidMethodV(clazz, id, args);
+ va_end(args);
}
+
template<typename T>
- static constexpr void assertJniPrimitiveType()
+ static constexpr void getFieldForType(JNIEnv *env, T &res, jobject obj, jfieldID id)
{
- if constexpr(!isJniPrimitiveType<T>())
- staticAssertTypeMismatch();
+ QtJniTypes::Caller<T>::getFieldForType(env, res, obj, id);
}
template<typename T>
- static constexpr void assertJniObjectType()
+ static constexpr void getStaticFieldForType(JNIEnv *env, T &res, jclass clazz, jfieldID id)
{
- if constexpr(!std::is_convertible<T, jobject>::value)
- staticAssertTypeMismatch();
+ QtJniTypes::Caller<T>::getStaticFieldForType(env, res, clazz, id);
}
template<typename T>
- static constexpr void assertJniType()
+ static constexpr void setFieldForType(JNIEnv *env, jobject obj, jfieldID id, T value)
{
- if constexpr(!isJniPrimitiveType<T>() && !std::is_convertible<T, jobject>::value)
- staticAssertTypeMismatch();
+ if constexpr (QtJniTypes::isObjectType<T>()) {
+ LocalFrame<T> frame(env);
+ env->SetObjectField(obj, id, static_cast<jobject>(frame.convertToJni(value)));
+ } else {
+ QtJniTypes::Caller<T>::setFieldForType(env, obj, id, value);
+ }
}
template<typename T>
- static constexpr const char* getTypeSignature()
- {
- if constexpr(std::is_same<T, jobject>::value)
- return "Ljava/lang/Object;";
- else if constexpr(std::is_same<T, jclass>::value)
- return "Ljava/lang/Class;";
- else if constexpr(std::is_same<T, jstring>::value)
- return "Ljava/lang/String;";
- else if constexpr(std::is_same<T, jobjectArray>::value)
- return "[Ljava/lang/Object;";
- else if constexpr(std::is_same<T, jthrowable>::value)
- return "Ljava/lang/Throwable;";
- else if constexpr(std::is_same<T, jbooleanArray>::value)
- return "[Z";
- else if constexpr(std::is_same<T, jbyteArray>::value)
- return "[B";
- else if constexpr(std::is_same<T, jshortArray>::value)
- return "[S";
- else if constexpr(std::is_same<T, jintArray>::value)
- return "[I";
- else if constexpr(std::is_same<T, jlongArray>::value)
- return "[J";
- else if constexpr(std::is_same<T, jfloatArray>::value)
- return "[F";
- else if constexpr(std::is_same<T, jdoubleArray>::value)
- return "[D";
- else if constexpr(std::is_same<T, jcharArray>::value)
- return "[C";
- else if constexpr(std::is_same<T, jboolean>::value)
- return "Z";
- else if constexpr(std::is_same<T, jbyte>::value)
- return "B";
- else if constexpr(std::is_same<T, jchar>::value)
- return "C";
- else if constexpr(std::is_same<T, jshort>::value)
- return "S";
- else if constexpr(std::is_same<T, jint>::value)
- return "I";
- else if constexpr(std::is_same<T, jlong>::value)
- return "J";
- else if constexpr(std::is_same<T, jfloat>::value)
- return "F";
- else if constexpr(std::is_same<T, jdouble>::value)
- return "D";
- else
- staticAssertTypeMismatch();
+ static constexpr void setStaticFieldForType(JNIEnv *env, jclass clazz, jfieldID id, T value)
+ {
+ if constexpr (QtJniTypes::isObjectType<T>()) {
+ LocalFrame<T> frame(env);
+ env->SetStaticObjectField(clazz, id, static_cast<jobject>(frame.convertToJni(value)));
+ } else {
+ QtJniTypes::Caller<T>::setStaticFieldForType(env, clazz, id, value);
+ }
}
- template<typename T>
- static constexpr void callMethodForType(JNIEnv *env, T &res, jobject obj,
- jmethodID id, va_list args)
- {
- if constexpr(std::is_same<T, jboolean>::value)
- res = env->CallBooleanMethodV(obj, id, args);
- else if constexpr(std::is_same<T, jbyte>::value)
- res = env->CallByteMethodV(obj, id, args);
- else if constexpr(std::is_same<T, jchar>::value)
- res = env->CallCharMethodV(obj, id, args);
- else if constexpr(std::is_same<T, jshort>::value)
- res = env->CallShortMethodV(obj, id, args);
- else if constexpr(std::is_same<T, jint>::value)
- res = env->CallIntMethodV(obj, id, args);
- else if constexpr(std::is_same<T, jlong>::value)
- res = env->CallLongMethodV(obj, id, args);
- else if constexpr(std::is_same<T, jfloat>::value)
- res = env->CallFloatMethodV(obj, id, args);
- else if constexpr(std::is_same<T, jdouble>::value)
- res = env->CallDoubleMethodV(obj, id, args);
- else
- staticAssertTypeMismatch();
+ friend QJniObjectPrivate;
+ QSharedPointer<QJniObjectPrivate> d;
+};
+
+inline bool operator==(const QJniObject &obj1, const QJniObject &obj2)
+{
+ return obj1.isSameObject(obj2);
+}
+
+inline bool operator!=(const QJniObject &obj1, const QJniObject &obj2)
+{
+ return !obj1.isSameObject(obj2);
+}
+
+namespace QtJniTypes {
+struct JObjectBase
+{
+ operator QJniObject() const { return m_object; }
+
+ bool isValid() const { return m_object.isValid(); }
+ jclass objectClass() const { return m_object.objectClass(); }
+ QString toString() const { return m_object.toString(); }
+
+ template <typename T = jobject>
+ T object() const {
+ return m_object.object<T>();
}
- template<typename T>
- static constexpr void callStaticMethodForType(JNIEnv *env, T &res, jclass clazz,
- jmethodID id, va_list args)
- {
- if constexpr(std::is_same<T, jboolean>::value)
- res = env->CallStaticBooleanMethodV(clazz, id, args);
- else if constexpr(std::is_same<T, jbyte>::value)
- res = env->CallStaticByteMethodV(clazz, id, args);
- else if constexpr(std::is_same<T, jchar>::value)
- res = env->CallStaticCharMethodV(clazz, id, args);
- else if constexpr(std::is_same<T, jshort>::value)
- res = env->CallStaticShortMethodV(clazz, id, args);
- else if constexpr(std::is_same<T, jint>::value)
- res = env->CallStaticIntMethodV(clazz, id, args);
- else if constexpr(std::is_same<T, jlong>::value)
- res = env->CallStaticLongMethodV(clazz, id, args);
- else if constexpr(std::is_same<T, jfloat>::value)
- res = env->CallStaticFloatMethodV(clazz, id, args);
- else if constexpr(std::is_same<T, jdouble>::value)
- res = env->CallStaticDoubleMethodV(clazz, id, args);
- else
- staticAssertTypeMismatch();
+protected:
+ JObjectBase() = default;
+ ~JObjectBase() = default;
+
+ Q_IMPLICIT JObjectBase(jobject object) : m_object(object) {}
+ Q_IMPLICIT JObjectBase(const QJniObject &object) : m_object(object) {}
+ Q_IMPLICIT JObjectBase(QJniObject &&object) noexcept : m_object(std::move(object)) {}
+
+ QJniObject m_object;
+};
+
+template<typename Type>
+class JObject : public JObjectBase
+{
+public:
+ using Class = Type;
+
+ JObject()
+ : JObjectBase{QJniObject(QtJniTypes::Traits<Class>::className())}
+ {}
+ Q_IMPLICIT JObject(jobject object) : JObjectBase(object) {}
+ Q_IMPLICIT JObject(const QJniObject &object) : JObjectBase(object) {}
+ Q_IMPLICIT JObject(QJniObject &&object) noexcept : JObjectBase(std::move(object)) {}
+
+ // base class destructor is protected, so need to provide all SMFs
+ JObject(const JObject &other) = default;
+ JObject(JObject &&other) noexcept = default;
+ JObject &operator=(const JObject &other) = default;
+ JObject &operator=(JObject &&other) noexcept = default;
+
+ ~JObject() = default;
+
+ template<typename Arg, typename ...Args
+ , std::enable_if_t<!std::is_same_v<Arg, JObject>, bool> = true
+ , IfValidSignatureTypes<Arg, Args...> = true
+ >
+ explicit JObject(Arg && arg, Args &&...args)
+ : JObjectBase{QJniObject(QtJniTypes::Traits<Class>::className(),
+ std::forward<Arg>(arg), std::forward<Args>(args)...)}
+ {}
+
+ // named constructors avoid ambiguities
+ static Type fromJObject(jobject object) { return Type(object); }
+ template <typename ...Args>
+ static Type construct(Args &&...args) { return Type(std::forward<Args>(args)...); }
+ static Type fromLocalRef(jobject lref) { return Type(QJniObject::fromLocalRef(lref)); }
+
+ static bool registerNativeMethods(std::initializer_list<JNINativeMethod> methods)
+ {
+ QJniEnvironment env;
+ return env.registerNativeMethods<Class>(methods);
}
- template<typename T>
- static constexpr void getFieldForType(JNIEnv *env, T &res, jobject obj,
- jfieldID id)
- {
- if constexpr(std::is_same<T, jboolean>::value)
- res = env->GetBooleanField(obj, id);
- else if constexpr(std::is_same<T, jbyte>::value)
- res = env->GetByteField(obj, id);
- else if constexpr(std::is_same<T, jchar>::value)
- res = env->GetCharField(obj, id);
- else if constexpr(std::is_same<T, jshort>::value)
- res = env->GetShortField(obj, id);
- else if constexpr(std::is_same<T, jint>::value)
- res = env->GetIntField(obj, id);
- else if constexpr(std::is_same<T, jlong>::value)
- res = env->GetLongField(obj, id);
- else if constexpr(std::is_same<T, jfloat>::value)
- res = env->GetFloatField(obj, id);
- else if constexpr(std::is_same<T, jdouble>::value)
- res = env->GetDoubleField(obj, id);
- else
- staticAssertTypeMismatch();
+ // public API forwarding to QJniObject, with the implicit Class template parameter
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ static auto callStaticMethod(const char *name, Args &&...args)
+ {
+ return QJniObject::callStaticMethod<Class, Ret, Args...>(name,
+ std::forward<Args>(args)...);
+ }
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ static auto getStaticField(const char *field)
+ {
+ return QJniObject::getStaticField<Class, T>(field);
+ }
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ static void setStaticField(const char *field, T &&value)
+ {
+ QJniObject::setStaticField<Class, T>(field, std::forward<T>(value));
}
- template<typename T>
- static constexpr void getStaticFieldForType(JNIEnv *env, T &res, jclass clazz,
- jfieldID id)
- {
- if constexpr(std::is_same<T, jboolean>::value)
- res = env->GetStaticBooleanField(clazz, id);
- else if constexpr(std::is_same<T, jbyte>::value)
- res = env->GetStaticByteField(clazz, id);
- else if constexpr(std::is_same<T, jchar>::value)
- res = env->GetStaticCharField(clazz, id);
- else if constexpr(std::is_same<T, jshort>::value)
- res = env->GetStaticShortField(clazz, id);
- else if constexpr(std::is_same<T, jint>::value)
- res = env->GetStaticIntField(clazz, id);
- else if constexpr(std::is_same<T, jlong>::value)
- res = env->GetStaticLongField(clazz, id);
- else if constexpr(std::is_same<T, jfloat>::value)
- res = env->GetStaticFloatField(clazz, id);
- else if constexpr(std::is_same<T, jdouble>::value)
- res = env->GetStaticDoubleField(clazz, id);
- else
- staticAssertTypeMismatch();
+ // keep only these overloads, the rest is made private
+ template <typename Ret, typename ...Args
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
+#endif
+ >
+ auto callMethod(const char *method, Args &&...args) const
+ {
+ return m_object.callMethod<Ret>(method, std::forward<Args>(args)...);
+ }
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ auto getField(const char *fieldName) const
+ {
+ return m_object.getField<T>(fieldName);
}
- template<typename T>
- static constexpr void setFieldForType(JNIEnv *env, jobject obj,
- jfieldID id, T value)
- {
- if constexpr(std::is_same<T, jboolean>::value)
- env->SetBooleanField(obj, id, value);
- else if constexpr(std::is_same<T, jbyte>::value)
- env->SetByteField(obj, id, value);
- else if constexpr(std::is_same<T, jchar>::value)
- env->SetCharField(obj, id, value);
- else if constexpr(std::is_same<T, jshort>::value)
- env->SetShortField(obj, id, value);
- else if constexpr(std::is_same<T, jint>::value)
- env->SetIntField(obj, id, value);
- else if constexpr(std::is_same<T, jlong>::value)
- env->SetLongField(obj, id, value);
- else if constexpr(std::is_same<T, jfloat>::value)
- env->SetFloatField(obj, id, value);
- else if constexpr(std::is_same<T, jdouble>::value)
- env->SetDoubleField(obj, id, value);
- else if constexpr(std::is_convertible<T, jobject>::value)
- env->SetObjectField(obj, id, value);
- else
- staticAssertTypeMismatch();
+ template <typename T
+#ifndef Q_QDOC
+ , QtJniTypes::IfValidFieldType<T> = true
+#endif
+ >
+ void setField(const char *fieldName, T &&value)
+ {
+ m_object.setField(fieldName, std::forward<T>(value));
}
- template<typename T>
- static constexpr void setStaticFieldForType(JNIEnv *env, jclass clazz,
- jfieldID id, T value)
- {
- if constexpr(std::is_same<T, jboolean>::value)
- env->SetStaticBooleanField(clazz, id, value);
- else if constexpr(std::is_same<T, jbyte>::value)
- env->SetStaticByteField(clazz, id, value);
- else if constexpr(std::is_same<T, jchar>::value)
- env->SetStaticCharField(clazz, id, value);
- else if constexpr(std::is_same<T, jshort>::value)
- env->SetStaticShortField(clazz, id, value);
- else if constexpr(std::is_same<T, jint>::value)
- env->SetStaticIntField(clazz, id, value);
- else if constexpr(std::is_same<T, jlong>::value)
- env->SetStaticLongField(clazz, id, value);
- else if constexpr(std::is_same<T, jfloat>::value)
- env->SetStaticFloatField(clazz, id, value);
- else if constexpr(std::is_same<T, jdouble>::value)
- env->SetStaticDoubleField(clazz, id, value);
- else if constexpr(std::is_convertible<T, jobject>::value)
- env->SetStaticObjectField(clazz, id, value);
- else
- staticAssertTypeMismatch();
+ QByteArray className() const {
+ return QtJniTypes::Traits<Class>::className().data();
}
- friend QJniObjectPrivate;
- QSharedPointer<QJniObjectPrivate> d;
+private:
+ friend bool comparesEqual(const JObject &lhs, const JObject &rhs) noexcept
+ { return lhs.m_object == rhs.m_object; }
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(JObject);
};
+}
-inline bool operator==(const QJniObject &obj1, const QJniObject &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.
+QT_END_NAMESPACE
+#include <QtCore/qjniarray.h>
+QT_BEGIN_NAMESPACE
+
+template <typename ...Args>
+template <typename T>
+auto QJniObject::LocalFrame<Args...>::convertToJni(T &&value)
{
- return obj1.isSameObject(obj2);
+ 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>
+ || std::is_base_of_v<QtJniTypes::JObjectBase, Type>) {
+ return value.object();
+ } else {
+ return std::forward<T>(value);
+ }
}
-inline bool operator!=(const QJniObject &obj1, const QJniObject &obj2)
+template <typename ...Args>
+template <typename T>
+auto QJniObject::LocalFrame<Args...>::convertFromJni(QJniObject &&object)
{
- return !obj1.isSameObject(obj2);
+ 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(std::move(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>()).toContainer();
+ } else if constexpr (std::is_array_v<Type>) {
+ using ElementType = std::remove_extent_t<Type>;
+ return QJniArray<ElementType>(std::move(object));
+ } else if constexpr (std::is_base_of_v<QJniObject, Type>
+ && !std::is_same_v<QJniObject, Type>) {
+ return T{std::move(object)};
+ } else if constexpr (std::is_base_of_v<QtJniTypes::JObjectBase, Type>) {
+ return T{std::move(object)};
+ } else {
+ return std::move(object);
+ }
}
+
QT_END_NAMESPACE
#endif