summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAssam Boudjelthia <assam.boudjelthia@qt.io>2021-04-15 16:52:44 +0300
committerAssam Boudjelthia <assam.boudjelthia@qt.io>2021-04-23 15:43:28 +0300
commitf4e23bf3deb69131f78eb78a1cb06da0fe72d9d4 (patch)
tree423bb588c65c6db91312f6e0ed9b1895f5daaa3f
parent2666f3e37d6c8f2125f77f8de2cf5582ead7c18e (diff)
Fix QJniObject templates implementations
Define the template calls in the header to allow for better type handling and checking with constexpr and avoid overuse of macros. Depending on the type provided in the QJniObject's call, the signatures and the correct JNI function variant is used. If a type is not supported a static_assert throws a compiler error. Pick-to: 6.1 6.1.0 Change-Id: I8a4d3ce85e1ff76ef385633f2a68511fffd12e55 Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io> Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
-rw-r--r--src/corelib/kernel/qjnienvironment.h8
-rw-r--r--src/corelib/kernel/qjniobject.cpp709
-rw-r--r--src/corelib/kernel/qjniobject.h672
-rw-r--r--tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp26
4 files changed, 722 insertions, 693 deletions
diff --git a/src/corelib/kernel/qjnienvironment.h b/src/corelib/kernel/qjnienvironment.h
index a9a3e99097..69a24cbe18 100644
--- a/src/corelib/kernel/qjnienvironment.h
+++ b/src/corelib/kernel/qjnienvironment.h
@@ -44,12 +44,6 @@
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
#include <jni.h>
-#else
-class JNIEnv;
-class JNINativeMethod;
-class JavaVM;
-class jclass;
-#endif
QT_BEGIN_NAMESPACE
@@ -82,4 +76,6 @@ private:
QT_END_NAMESPACE
+#endif
+
#endif // QJNI_ENVIRONMENT_H
diff --git a/src/corelib/kernel/qjniobject.cpp b/src/corelib/kernel/qjniobject.cpp
index 418a404bb4..dbca5321a1 100644
--- a/src/corelib/kernel/qjniobject.cpp
+++ b/src/corelib/kernel/qjniobject.cpp
@@ -39,11 +39,11 @@
#include "qjniobject.h"
-#include "qjnienvironment.h"
#include "qjnihelpers_p.h"
-#include <QtCore/QReadWriteLock>
-#include <QtCore/QHash>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qreadwritelock.h>
QT_BEGIN_NAMESPACE
@@ -286,6 +286,35 @@ QT_BEGIN_NAMESPACE
Returns true if \a o1 holds a reference to a different object than \a o2.
*/
+class QJniObjectPrivate
+{
+public:
+ QJniObjectPrivate() = default;
+ ~QJniObjectPrivate() {
+ QJniEnvironment env;
+ if (m_jobject)
+ env->DeleteGlobalRef(m_jobject);
+ if (m_jclass && m_own_jclass)
+ env->DeleteGlobalRef(m_jclass);
+ }
+
+ friend jclass QtAndroidPrivate::findClass(const char *className, JNIEnv *env);
+ static jclass loadClass(const QByteArray &className, JNIEnv *env, bool binEncoded = false)
+ {
+ return QJniObject::loadClass(className, env, binEncoded);
+ }
+
+ static QByteArray toBinaryEncClassName(const QByteArray &className)
+ {
+ return QJniObject::toBinaryEncClassName(className);
+ }
+
+ jobject m_jobject = nullptr;
+ jclass m_jclass = nullptr;
+ bool m_own_jclass = true;
+ QByteArray m_className;
+};
+
static inline QLatin1String keyBase()
{
return QLatin1String("%1%2:%3");
@@ -304,11 +333,6 @@ typedef QHash<QString, jclass> JClassHash;
Q_GLOBAL_STATIC(JClassHash, cachedClasses)
Q_GLOBAL_STATIC(QReadWriteLock, cachedClassesLock)
-static QByteArray toBinaryEncClassName(const QByteArray &className)
-{
- return QByteArray(className).replace('/', '.');
-}
-
static jclass getCachedClass(const QByteArray &classBinEnc, bool *isCached = nullptr)
{
QReadLocker locker(cachedClassesLock);
@@ -321,9 +345,14 @@ static jclass getCachedClass(const QByteArray &classBinEnc, bool *isCached = nul
return found ? it.value() : 0;
}
-inline static jclass loadClass(const QByteArray &className, JNIEnv *env, bool binEncoded = false)
+QByteArray QJniObject::toBinaryEncClassName(const QByteArray &className)
+{
+ return QByteArray(className).replace('/', '.');
+}
+
+jclass QJniObject::loadClass(const QByteArray &className, JNIEnv *env, bool binEncoded)
{
- const QByteArray &binEncClassName = binEncoded ? className : toBinaryEncClassName(className);
+ const QByteArray &binEncClassName = binEncoded ? className : QJniObject::toBinaryEncClassName(className);
bool isCached = false;
jclass clazz = getCachedClass(binEncClassName, &isCached);
@@ -357,11 +386,11 @@ typedef QHash<QString, jmethodID> JMethodIDHash;
Q_GLOBAL_STATIC(JMethodIDHash, cachedMethodID)
Q_GLOBAL_STATIC(QReadWriteLock, cachedMethodIDLock)
-static inline jmethodID getMethodID(JNIEnv *env,
+jmethodID QJniObject::getMethodID(JNIEnv *env,
jclass clazz,
const char *name,
const char *signature,
- bool isStatic = false)
+ bool isStatic)
{
jmethodID id = isStatic ? env->GetStaticMethodID(clazz, name, signature)
: env->GetMethodID(clazz, name, signature);
@@ -372,12 +401,17 @@ static inline jmethodID getMethodID(JNIEnv *env,
return id;
}
-static jmethodID getCachedMethodID(JNIEnv *env,
- jclass clazz,
- const QByteArray &className,
- const char *name,
- const char *signature,
- bool isStatic = false)
+void QJniObject::callVoidMethodV(JNIEnv *env, jmethodID id, va_list args) const
+{
+ env->CallVoidMethodV(d->m_jobject, id, args);
+}
+
+jmethodID QJniObject::getCachedMethodID(JNIEnv *env,
+ jclass clazz,
+ const QByteArray &className,
+ const char *name,
+ const char *signature,
+ bool isStatic)
{
if (className.isEmpty())
return getMethodID(env, clazz, name, signature, isStatic);
@@ -407,15 +441,21 @@ static jmethodID getCachedMethodID(JNIEnv *env,
}
}
+jmethodID QJniObject::getCachedMethodID(JNIEnv *env, const char *name,
+ const char *signature, bool isStatic) const
+{
+ return QJniObject::getCachedMethodID(env, d->m_jclass, d->m_className, name, signature, isStatic);
+}
+
typedef QHash<QString, jfieldID> JFieldIDHash;
Q_GLOBAL_STATIC(JFieldIDHash, cachedFieldID)
Q_GLOBAL_STATIC(QReadWriteLock, cachedFieldIDLock)
-static inline jfieldID getFieldID(JNIEnv *env,
- jclass clazz,
- const char *name,
- const char *signature,
- bool isStatic = false)
+jfieldID QJniObject::getFieldID(JNIEnv *env,
+ jclass clazz,
+ const char *name,
+ const char *signature,
+ bool isStatic)
{
jfieldID id = isStatic ? env->GetStaticFieldID(clazz, name, signature)
: env->GetFieldID(clazz, name, signature);
@@ -426,12 +466,12 @@ static inline jfieldID getFieldID(JNIEnv *env,
return id;
}
-static jfieldID getCachedFieldID(JNIEnv *env,
- jclass clazz,
- const QByteArray &className,
- const char *name,
- const char *signature,
- bool isStatic = false)
+jfieldID QJniObject::getCachedFieldID(JNIEnv *env,
+ jclass clazz,
+ const QByteArray &className,
+ const char *name,
+ const char *signature,
+ bool isStatic)
{
if (className.isNull())
return getFieldID(env, clazz, name, signature, isStatic);
@@ -461,9 +501,17 @@ static jfieldID getCachedFieldID(JNIEnv *env,
}
}
+jfieldID QJniObject::getCachedFieldID(JNIEnv *env,
+ const char *name,
+ const char *signature,
+ bool isStatic) const
+{
+ return QJniObject::getCachedFieldID(env, d->m_jclass, d->m_className, name, signature, isStatic);
+}
+
jclass QtAndroidPrivate::findClass(const char *className, JNIEnv *env)
{
- const QByteArray &classDotEnc = toBinaryEncClassName(className);
+ const QByteArray &classDotEnc = QJniObjectPrivate::toBinaryEncClassName(className);
bool isCached = false;
jclass clazz = getCachedClass(classDotEnc, &isCached);
@@ -489,29 +537,11 @@ jclass QtAndroidPrivate::findClass(const char *className, JNIEnv *env)
}
if (!clazz) // We didn't get an env. pointer or we got one with the WRONG class loader...
- clazz = loadClass(classDotEnc, QJniEnvironment().jniEnv(), true);
+ clazz = QJniObjectPrivate::loadClass(classDotEnc, QJniEnvironment().jniEnv(), true);
return clazz;
}
-class QJniObjectPrivate
-{
-public:
- QJniObjectPrivate() = default;
- ~QJniObjectPrivate() {
- QJniEnvironment env;
- if (m_jobject)
- env->DeleteGlobalRef(m_jobject);
- if (m_jclass && m_own_jclass)
- env->DeleteGlobalRef(m_jclass);
- }
-
- jobject m_jobject = nullptr;
- jclass m_jclass = nullptr;
- bool m_own_jclass = true;
- QByteArray m_className;
-};
-
/*!
\fn QJniObject::QJniObject()
@@ -542,7 +572,7 @@ QJniObject::QJniObject(const char *className)
d->m_own_jclass = false;
if (d->m_jclass) {
// get default constructor
- jmethodID constructorId = getCachedMethodID(env.jniEnv(), d->m_jclass, d->m_className, "<init>", "()V");
+ jmethodID constructorId = getCachedMethodID(env.jniEnv(), "<init>", "()V");
if (constructorId) {
jobject obj = env->NewObject(d->m_jclass, constructorId);
if (obj) {
@@ -574,7 +604,7 @@ QJniObject::QJniObject(const char *className, const char *signature, ...)
d->m_jclass = loadClass(d->m_className, env.jniEnv(), true);
d->m_own_jclass = false;
if (d->m_jclass) {
- jmethodID constructorId = getCachedMethodID(env.jniEnv(), d->m_jclass, d->m_className, "<init>", signature);
+ jmethodID constructorId = getCachedMethodID(env.jniEnv(), "<init>", signature);
if (constructorId) {
va_list args;
va_start(args, signature);
@@ -596,7 +626,7 @@ QJniObject::QJniObject(const char *className, const char *signature, const QVaLi
d->m_jclass = loadClass(d->m_className, env.jniEnv(), true);
d->m_own_jclass = false;
if (d->m_jclass) {
- jmethodID constructorId = getCachedMethodID(env.jniEnv(), d->m_jclass, d->m_className, "<init>", signature);
+ jmethodID constructorId = getCachedMethodID(env.jniEnv(), "<init>", signature);
if (constructorId) {
jobject obj = env->NewObjectV(d->m_jclass, constructorId, args);
if (obj) {
@@ -720,7 +750,7 @@ QJniObject::QJniObject(jobject obj)
exception clearing and delete the local reference before returning.
The JNI object can be null if there was an exception.
*/
-inline static QJniObject getCleanJniObject(jobject obj)
+QJniObject QJniObject::getCleanJniObject(jobject obj)
{
if (!obj)
return QJniObject();
@@ -772,7 +802,7 @@ QJniObject QJniObject::callObjectMethodV(const char *methodName,
{
QJniEnvironment env;
jobject res = nullptr;
- jmethodID id = getCachedMethodID(env.jniEnv(), d->m_jclass, d->m_className, methodName, signature);
+ jmethodID id = getCachedMethodID(env.jniEnv(), methodName, signature);
if (id) {
res = env->CallObjectMethodV(d->m_jobject, id, args);
if (env.checkAndClearExceptions()) {
@@ -795,7 +825,7 @@ QJniObject QJniObject::callStaticObjectMethodV(const char *className,
jobject res = nullptr;
jclass clazz = loadClass(className, env.jniEnv());
if (clazz) {
- jmethodID id = getCachedMethodID(env.jniEnv(), clazz, toBinaryEncClassName(className),
+ jmethodID id = QJniObject::getCachedMethodID(env.jniEnv(), clazz, toBinaryEncClassName(className),
methodName, signature, true);
if (id) {
res = env->CallStaticObjectMethodV(clazz, id, args);
@@ -836,19 +866,6 @@ QJniObject QJniObject::callStaticObjectMethodV(jclass clazz,
\endcode
*/
-template <>
-Q_CORE_EXPORT void QJniObject::callMethod<void>(const char *methodName, const char *signature, ...) const
-{
- QJniEnvironment env;
- jmethodID id = getCachedMethodID(env.jniEnv(), d->m_jclass, d->m_className, methodName, signature);
- if (id) {
- va_list args;
- va_start(args, signature);
- env->CallVoidMethodV(d->m_jobject, id, args);
- va_end(args);
- env.checkAndClearExceptions();
- }
-}
/*!
\fn template <typename T> T QJniObject::callMethod(const char *methodName) const
@@ -860,11 +877,6 @@ Q_CORE_EXPORT void QJniObject::callMethod<void>(const char *methodName, const ch
jint size = myJavaString.callMethod<jint>("length");
\endcode
*/
-template <>
-Q_CORE_EXPORT void QJniObject::callMethod<void>(const char *methodName) const
-{
- callMethod<void>(methodName, "()V");
-}
/*!
\fn template <typename T> T QJniObject::callStaticMethod(const char *className, const char *methodName, const char *signature, ...)
@@ -878,26 +890,6 @@ Q_CORE_EXPORT void QJniObject::callMethod<void>(const char *methodName) const
jint max = QJniObject::callStaticMethod<jint>("java/lang/Math", "max", "(II)I", a, b);
\endcode
*/
-template <>
-Q_CORE_EXPORT void QJniObject::callStaticMethod<void>(const char *className,
- const char *methodName,
- const char *signature,
- ...)
-{
- QJniEnvironment env;
- jclass clazz = loadClass(className, env.jniEnv());
- if (clazz) {
- jmethodID id = getCachedMethodID(env.jniEnv(), clazz, toBinaryEncClassName(className),
- methodName, signature, true);
- if (id) {
- va_list args;
- va_start(args, signature);
- env->CallStaticVoidMethodV(clazz, id, args);
- va_end(args);
- env.checkAndClearExceptions();
- }
- }
-}
/*!
\fn template <typename T> T QJniObject::callStaticMethod(const char *className, const char *methodName)
@@ -908,11 +900,6 @@ Q_CORE_EXPORT void QJniObject::callStaticMethod<void>(const char *className,
jint value = QJniObject::callStaticMethod<jint>("MyClass", "staticMethod");
\endcode
*/
-template <>
-Q_CORE_EXPORT void QJniObject::callStaticMethod<void>(const char *className, const char *methodName)
-{
- callStaticMethod<void>(className, methodName, "()V");
-}
/*!
\fn template <typename T> T QJniObject::callStaticMethod(jclass clazz, const char *methodName, const char *signature, ...)
@@ -928,57 +915,6 @@ Q_CORE_EXPORT void QJniObject::callStaticMethod<void>(const char *className, con
jint max = QJniObject::callStaticMethod<jint>(javaMathClass, "max", "(II)I", a, b);
\endcode
*/
-template <>
-Q_CORE_EXPORT void QJniObject::callStaticMethod<void>(jclass clazz,
- const char *methodName,
- const char *signature,
- ...)
-{
- 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();
- }
- }
-}
-
-template <>
-Q_CORE_EXPORT void QJniObject::callStaticMethodV<void>(const char *className,
- const char *methodName,
- const char *signature,
- va_list args)
-{
- QJniEnvironment env;
- jclass clazz = loadClass(className, env.jniEnv());
- if (clazz) {
- jmethodID id = getCachedMethodID(env.jniEnv(), clazz,
- toBinaryEncClassName(className), methodName,
- signature, true);
- if (id) {
- env->CallStaticVoidMethodV(clazz, id, args);
- env.checkAndClearExceptions();
- }
- }
-}
-
-template <>
-Q_CORE_EXPORT void QJniObject::callStaticMethodV<void>(jclass clazz,
- const char *methodName,
- const char *signature,
- va_list args)
-{
- QJniEnvironment env;
- jmethodID id = getMethodID(env.jniEnv(), clazz, methodName, signature, true);
- if (id) {
- env->CallStaticVoidMethodV(clazz, id, args);
- env.checkAndClearExceptions();
- }
-}
/*!
\fn template <typename T> T QJniObject::callStaticMethod(jclass clazz, const char *methodName)
@@ -991,161 +927,6 @@ Q_CORE_EXPORT void QJniObject::callStaticMethodV<void>(jclass clazz,
jdouble randNr = QJniObject::callStaticMethod<jdouble>(javaMathClass, "random");
\endcode
*/
-template <>
-Q_CORE_EXPORT void QJniObject::callStaticMethod<void>(jclass clazz, const char *methodName)
-{
- callStaticMethod<void>(clazz, methodName, "()V");
-}
-
-template <>
-Q_CORE_EXPORT void QJniObject::callMethodV<void>(const char *methodName, const char *signature,
- va_list args) const
-{
- QJniEnvironment env;
- jmethodID id = getCachedMethodID(env.jniEnv(), d->m_jclass, d->m_className, methodName, signature);
- if (id) {
- env->CallVoidMethodV(d->m_jobject, id, args);
- env.checkAndClearExceptions();
- }
-}
-
-#define MAKE_JNI_METHODS(MethodName, Type, Signature) \
-template <> Q_CORE_EXPORT Type QJniObject::callMethod<Type>(const char *methodName, \
- const char *signature, ...) const \
-{ \
- QJniEnvironment env; \
- Type res = 0; \
- jmethodID id = getCachedMethodID(env.jniEnv(), d->m_jclass, d->m_className, methodName, signature); \
- if (id) { \
- va_list args; \
- va_start(args, signature); \
- res = env->Call##MethodName##MethodV(d->m_jobject, id, args); \
- va_end(args); \
- if (env.checkAndClearExceptions()) \
- res = 0; \
- } \
- return res; \
-}\
-template <> Q_CORE_EXPORT Type QJniObject::callMethod<Type>(const char *methodName) const \
-{ \
- return callMethod<Type>(methodName, Signature); \
-} \
-\
-template <> Q_CORE_EXPORT Type QJniObject::callStaticMethod<Type>(const char *className, \
- const char *methodName, \
- const char *signature, \
- ...) \
-{ \
- QJniEnvironment env; \
- Type res = 0; \
- jclass clazz = loadClass(className, env.jniEnv()); \
- if (clazz) { \
- jmethodID id = getCachedMethodID(env.jniEnv(), clazz, toBinaryEncClassName(className), methodName, \
- signature, true); \
- if (id) { \
- va_list args; \
- va_start(args, signature); \
- res = env->CallStatic##MethodName##MethodV(clazz, id, args); \
- va_end(args); \
- if (env.checkAndClearExceptions()) \
- res = 0; \
- } \
- } \
- return res; \
-} \
-template <> Q_CORE_EXPORT Type QJniObject::callStaticMethod<Type>(const char *className, \
- const char *methodName) \
-{ \
- return callStaticMethod<Type>(className, methodName, Signature); \
-}\
-\
-template <> Q_CORE_EXPORT Type QJniObject::callStaticMethod<Type>(jclass clazz, \
- const char *methodName, \
- const char *signature, \
- ...) \
-{ \
- QJniEnvironment env; \
- Type res = 0; \
- if (clazz) { \
- jmethodID id = getMethodID(env.jniEnv(), clazz, methodName, signature, true); \
- if (id) { \
- va_list args; \
- va_start(args, signature); \
- res = env->CallStatic##MethodName##MethodV(clazz, id, args); \
- va_end(args); \
- if (env.checkAndClearExceptions()) \
- res = 0; \
- } \
- } \
- return res; \
-} \
-template <> Q_CORE_EXPORT Type QJniObject::callStaticMethod<Type>(jclass clazz, \
- const char *methodName) \
-{ \
- return callStaticMethod<Type>(clazz, methodName, Signature); \
-}\
-template <> \
-Q_CORE_EXPORT Type QJniObject::callMethodV<Type>(const char *methodName, const char *signature,\
- va_list args) const\
-{\
- QJniEnvironment env;\
- Type res = 0;\
- jmethodID id = getCachedMethodID(env.jniEnv(), d->m_jclass, d->m_className, methodName, signature);\
- if (id) {\
- res = env->Call##MethodName##MethodV(d->m_jobject, id, args);\
- if (env.checkAndClearExceptions()) \
- res = 0; \
- }\
- return res;\
-}\
-template <>\
-Q_CORE_EXPORT Type QJniObject::callStaticMethodV<Type>(const char *className,\
- const char *methodName,\
- const char *signature,\
- va_list args)\
-{\
- QJniEnvironment env;\
- Type res = 0;\
- jclass clazz = loadClass(className, env.jniEnv());\
- if (clazz) {\
- jmethodID id = getCachedMethodID(env.jniEnv(), clazz, toBinaryEncClassName(className), methodName,\
- signature, true);\
- if (id) {\
- res = env->CallStatic##MethodName##MethodV(clazz, id, args);\
- if (env.checkAndClearExceptions()) \
- res = 0; \
- }\
- }\
- return res;\
-}\
-template <>\
-Q_CORE_EXPORT Type QJniObject::callStaticMethodV<Type>(jclass clazz,\
- const char *methodName,\
- const char *signature,\
- va_list args)\
-{\
- QJniEnvironment env;\
- Type res = 0;\
- jmethodID id = getMethodID(env.jniEnv(), clazz, methodName, signature, true);\
- if (id) {\
- res = env->CallStatic##MethodName##MethodV(clazz, id, args);\
- if (env.checkAndClearExceptions()) \
- res = 0; \
- }\
- return res;\
-}
-
-#define DECLARE_JNI_METHODS(MethodName, Type, Signature) MAKE_JNI_METHODS(MethodName, \
- Type, \
- Signature)
-DECLARE_JNI_METHODS(Boolean, jboolean, "()Z")
-DECLARE_JNI_METHODS(Byte, jbyte, "()B")
-DECLARE_JNI_METHODS(Char, jchar, "()C")
-DECLARE_JNI_METHODS(Short, jshort, "()S")
-DECLARE_JNI_METHODS(Int, jint, "()I")
-DECLARE_JNI_METHODS(Long, jlong, "()J")
-DECLARE_JNI_METHODS(Float, jfloat, "()F")
-DECLARE_JNI_METHODS(Double, jdouble, "()D")
/*!
\fn QJniObject QJniObject::callObjectMethod(const char *methodName, const char *signature, ...) const
@@ -1162,7 +943,7 @@ DECLARE_JNI_METHODS(Double, jdouble, "()D")
QJniObject QJniObject::callObjectMethod(const char *methodName, const char *signature, ...) const
{
QJniEnvironment env;
- jmethodID id = getCachedMethodID(env.jniEnv(), d->m_jclass, d->m_className, methodName, signature);
+ jmethodID id = getCachedMethodID(env.jniEnv(), methodName, signature);
if (id) {
va_list args;
va_start(args, signature);
@@ -1187,15 +968,14 @@ QJniObject QJniObject::callObjectMethod(const char *methodName, const char *sign
"(I)Ljava/lang/String;", 10);
\endcode
*/
-QJniObject QJniObject::callStaticObjectMethod(const char *className,
- const char *methodName,
- const char *signature,
- ...)
+QJniObject QJniObject::callStaticObjectMethod(const char *className, const char *methodName,
+ const char *signature, ...)
{
QJniEnvironment env;
- jclass clazz = loadClass(className, env.jniEnv());
+ jclass clazz = QJniObject::loadClass(className, env.jniEnv());
if (clazz) {
- jmethodID id = getCachedMethodID(env.jniEnv(), clazz, toBinaryEncClassName(className),
+ jmethodID id = QJniObject::getCachedMethodID(env.jniEnv(), clazz,
+ QJniObject::toBinaryEncClassName(className),
methodName, signature, true);
if (id) {
va_list args;
@@ -1215,10 +995,8 @@ QJniObject QJniObject::callStaticObjectMethod(const char *className,
Calls the static method \a methodName from class \a clazz with \a signature
specifying the types of any subsequent arguments.
*/
-QJniObject QJniObject::callStaticObjectMethod(jclass clazz,
- const char *methodName,
- const char *signature,
- ...)
+QJniObject QJniObject::callStaticObjectMethod(jclass clazz, const char *methodName,
+ const char *signature, ...)
{
QJniEnvironment env;
if (clazz) {
@@ -1289,51 +1067,6 @@ QJniObject QJniObject::callStaticObjectMethod(jclass clazz,
Replace the current object with \a object. The old Java object will be released.
*/
-#define MAKE_JNI_OBJECT_METHODS(Type, Signature) \
-template <> \
-Q_CORE_EXPORT QJniObject QJniObject::callObjectMethod<Type>(const char *methodName) const \
-{ \
- return callObjectMethod(methodName, Signature); \
-} \
-template <> \
-Q_CORE_EXPORT QJniObject QJniObject::callStaticObjectMethod<Type>(const char *className, \
- const char *methodName) \
-{ \
- return callStaticObjectMethod(className, methodName, Signature); \
-} \
-template <> \
-Q_CORE_EXPORT QJniObject QJniObject::callStaticObjectMethod<Type>(jclass clazz, \
- const char *methodName) \
-{ \
- return callStaticObjectMethod(clazz, methodName, Signature); \
-}\
-template <>\
-Q_CORE_EXPORT Type QJniObject::object<Type>() const\
-{\
- return static_cast<Type>(javaObject());\
-}\
-template <>\
-Q_CORE_EXPORT QJniObject &QJniObject::operator=(Type obj)\
-{\
- assign(static_cast<jobject>(obj));\
- return *this;\
-}
-
-#define DECLARE_JNI_OBJECT_METHODS(Type, Signature) MAKE_JNI_OBJECT_METHODS(Type, Signature)
-
-DECLARE_JNI_OBJECT_METHODS(jobject, "()Ljava/lang/Object;")
-DECLARE_JNI_OBJECT_METHODS(jclass, "()Ljava/lang/Class;")
-DECLARE_JNI_OBJECT_METHODS(jstring, "()Ljava/lang/String;")
-DECLARE_JNI_OBJECT_METHODS(jobjectArray, "()[Ljava/lang/Object;")
-DECLARE_JNI_OBJECT_METHODS(jbooleanArray, "()[Z")
-DECLARE_JNI_OBJECT_METHODS(jbyteArray, "()[B")
-DECLARE_JNI_OBJECT_METHODS(jshortArray, "()[S")
-DECLARE_JNI_OBJECT_METHODS(jintArray, "()[I")
-DECLARE_JNI_OBJECT_METHODS(jlongArray, "()[J")
-DECLARE_JNI_OBJECT_METHODS(jfloatArray, "()[F")
-DECLARE_JNI_OBJECT_METHODS(jdoubleArray, "()[D")
-DECLARE_JNI_OBJECT_METHODS(jcharArray, "()[C")
-DECLARE_JNI_OBJECT_METHODS(jthrowable, "()Ljava/lang/Throwable;")
/*!
\fn template <typename T> void QJniObject::setStaticField(const char *className, const char *fieldName, const char *signature, T value);
@@ -1342,24 +1075,6 @@ DECLARE_JNI_OBJECT_METHODS(jthrowable, "()Ljava/lang/Throwable;")
using the setter with \a signature.
*/
-template <>
-Q_CORE_EXPORT void QJniObject::setStaticField<jobject>(const char *className,
- const char *fieldName,
- const char *signature,
- jobject value)
-{
- QJniEnvironment env;
- jclass clazz = loadClass(className, env.jniEnv());
-
- if (!clazz)
- return;
-
- jfieldID id = getCachedFieldID(env.jniEnv(), clazz, className, fieldName, signature, true);
- if (id) {
- env->SetStaticObjectField(clazz, id, value);
- env.checkAndClearExceptions();
- }
-}
/*!
\fn template <typename T> void QJniObject::setStaticField(jclass clazz, const char *fieldName, const char *signature, T value);
@@ -1367,19 +1082,6 @@ Q_CORE_EXPORT void QJniObject::setStaticField<jobject>(const char *className,
Sets the static field \a fieldName on the class \a clazz to \a value using
the setter with \a signature.
*/
-template <> Q_CORE_EXPORT void QJniObject::setStaticField<jobject>(jclass clazz,
- const char *fieldName,
- const char *signature,
- jobject value)
-{
- QJniEnvironment env;
- jfieldID id = getFieldID(env.jniEnv(), clazz, fieldName, signature, true);
-
- if (id) {
- env->SetStaticObjectField(clazz, id, value);
- env.checkAndClearExceptions();
- }
-}
/*!
\fn T QJniObject::getField(const char *fieldName) const
@@ -1415,93 +1117,6 @@ template <> Q_CORE_EXPORT void QJniObject::setStaticField<jobject>(jclass clazz,
Sets the static field \a fieldName of the class \a clazz to \a value.
*/
-#define MAKE_JNI_PRIMITIVE_FIELDS(FieldName, Type, Signature) \
-template <> Q_CORE_EXPORT Type QJniObject::getField<Type>(const char *fieldName) const \
-{ \
- QJniEnvironment env; \
- Type res = 0; \
- jfieldID id = getCachedFieldID(env.jniEnv(), d->m_jclass, d->m_className, fieldName, Signature); \
- if (id) {\
- res = env->Get##FieldName##Field(d->m_jobject, id); \
- if (env.checkAndClearExceptions()) \
- res = 0; \
- } \
- return res;\
-} \
-template <> \
-Q_CORE_EXPORT Type QJniObject::getStaticField<Type>(const char *className, const char *fieldName) \
-{ \
- QJniEnvironment env; \
- jclass clazz = loadClass(className, env.jniEnv()); \
- if (!clazz) \
- return 0; \
- jfieldID id = getCachedFieldID(env.jniEnv(), clazz, toBinaryEncClassName(className), fieldName, \
- Signature, true); \
- if (!id) \
- return 0; \
- Type res = env->GetStatic##FieldName##Field(clazz, id); \
- if (env.checkAndClearExceptions()) \
- res = 0; \
- return res;\
-} \
-template <>\
-Q_CORE_EXPORT Type QJniObject::getStaticField<Type>(jclass clazz, const char *fieldName)\
-{\
- QJniEnvironment env;\
- Type res = 0;\
- jfieldID id = getFieldID(env.jniEnv(), clazz, fieldName, Signature, true);\
- if (id) {\
- res = env->GetStatic##FieldName##Field(clazz, id);\
- if (env.checkAndClearExceptions()) \
- res = 0; \
- }\
- return res;\
-}\
-template <> Q_CORE_EXPORT void QJniObject::setStaticField<Type>(const char *className, \
- const char *fieldName, \
- Type value) \
-{ \
- QJniEnvironment env; \
- jclass clazz = loadClass(className, env.jniEnv()); \
- if (!clazz) \
- return; \
- jfieldID id = getCachedFieldID(env.jniEnv(), clazz, className, fieldName, Signature, true); \
- if (!id) \
- return; \
- env->SetStatic##FieldName##Field(clazz, id, value); \
- env.checkAndClearExceptions(); \
-}\
-template <> Q_CORE_EXPORT void QJniObject::setStaticField<Type>(jclass clazz,\
- const char *fieldName,\
- Type value)\
-{\
- QJniEnvironment env;\
- jfieldID id = getFieldID(env.jniEnv(), clazz, fieldName, Signature, true);\
- if (id) {\
- env->SetStatic##FieldName##Field(clazz, id, value);\
- env.checkAndClearExceptions();\
- }\
-}\
-template <> Q_CORE_EXPORT void QJniObject::setField<Type>(const char *fieldName, Type value) \
-{ \
- QJniEnvironment env; \
- jfieldID id = getCachedFieldID(env.jniEnv(), d->m_jclass, d->m_className, fieldName, Signature); \
- if (id) { \
- env->Set##FieldName##Field(d->m_jobject, id, value); \
- env.checkAndClearExceptions(); \
- } \
-} \
-
-#define DECLARE_JNI_PRIMITIVE_FIELDS(FieldName, Type, Signature) MAKE_JNI_PRIMITIVE_FIELDS(FieldName, Type, \
- Signature)
-DECLARE_JNI_PRIMITIVE_FIELDS(Boolean, jboolean, "Z")
-DECLARE_JNI_PRIMITIVE_FIELDS(Byte, jbyte, "B")
-DECLARE_JNI_PRIMITIVE_FIELDS(Char, jchar, "C")
-DECLARE_JNI_PRIMITIVE_FIELDS(Short, jshort, "S")
-DECLARE_JNI_PRIMITIVE_FIELDS(Int, jint, "I")
-DECLARE_JNI_PRIMITIVE_FIELDS(Long, jlong, "J")
-DECLARE_JNI_PRIMITIVE_FIELDS(Float, jfloat, "F")
-DECLARE_JNI_PRIMITIVE_FIELDS(Double, jdouble, "D")
/*!
\fn QJniObject QJniObject::getStaticObjectField(const char *className, const char *fieldName, const char *signature)
@@ -1521,10 +1136,12 @@ QJniObject QJniObject::getStaticObjectField(const char *className,
const char *signature)
{
QJniEnvironment env;
- jclass clazz = loadClass(className, env.jniEnv());
+ jclass clazz = QJniObject::loadClass(className, env.jniEnv());
if (!clazz)
return QJniObject();
- jfieldID id = getCachedFieldID(env.jniEnv(), clazz, toBinaryEncClassName(className), fieldName,
+ jfieldID id = QJniObject::getCachedFieldID(env.jniEnv(), clazz,
+ QJniObject::toBinaryEncClassName(className),
+ fieldName,
signature, true);
if (!id)
return QJniObject();
@@ -1544,8 +1161,7 @@ QJniObject QJniObject::getStaticObjectField(const char *className,
QJniObject jobj = QJniObject::getStaticObjectField(clazz, "FIELD_NAME", "Ljava/lang/String;");
\endcode
*/
-QJniObject QJniObject::getStaticObjectField(jclass clazz,
- const char *fieldName,
+QJniObject QJniObject::getStaticObjectField(jclass clazz, const char *fieldName,
const char *signature)
{
QJniEnvironment env;
@@ -1557,62 +1173,6 @@ QJniObject QJniObject::getStaticObjectField(jclass clazz,
}
/*!
- \fn QJniObject QJniObject::getStaticObjectField<jobject>(jclass clazz, const char *fieldName, const char *signature)
-
- Retrieves a JNI object for \c jobject from the static field \a fieldName with
- \a signature from \a clazz.
-*/
-template <>
-Q_CORE_EXPORT QJniObject QJniObject::getStaticObjectField<jobject>(jclass clazz,
- const char *fieldName,
- const char *signature)
-{
- return getStaticObjectField(clazz, fieldName, signature);
-}
-
-/*!
- \fn QJniObject QJniObject::getStaticObjectField<jobject>(const char *className, const char *fieldName, const char *signature)
-
- Retrieves a JNI object for \c jobject from the static field \a fieldName with
- \a signature from class \a className.
-*/
-template <>
-Q_CORE_EXPORT QJniObject QJniObject::getStaticObjectField<jobject>(const char *className,
- const char *fieldName,
- const char *signature)
-{
- return getStaticObjectField(className, fieldName, signature);
-}
-
-/*!
- \fn QJniObject QJniObject::getStaticObjectField<jobjectArray>(jclass clazz, const char *fieldName, const char *signature)
-
- Retrieves a JNI object for \c jobjectArray from the static field \a fieldName
- with \a signature from class \a clazz.
-*/
-template <>
-Q_CORE_EXPORT QJniObject QJniObject::getStaticObjectField<jobjectArray>(jclass clazz,
- const char *fieldName,
- const char *signature)
-{
- return getStaticObjectField(clazz, fieldName, signature);
-}
-
-/*!
- \fn QJniObject QJniObject::getStaticObjectField<jobjectArray>(const char *className, const char *fieldName, const char *signature)
-
- Retrieves a JNI object for \c jobjectArray from the static field \a fieldName
- with \a signature from class \a className.
-*/
-template <>
-Q_CORE_EXPORT QJniObject QJniObject::getStaticObjectField<jobjectArray>(const char *className,
- const char *fieldName,
- const char *signature)
-{
- return getStaticObjectField(className, fieldName, signature);
-}
-
-/*!
\fn template <typename T> void QJniObject::setField(const char *fieldName, const char *signature, T value)
Sets the value of \a fieldName with \a signature to \a value.
@@ -1620,33 +1180,10 @@ Q_CORE_EXPORT QJniObject QJniObject::getStaticObjectField<jobjectArray>(const ch
\code
QJniObject stringArray = ...;
QJniObject obj = ...;
- obj.setField<jobjectArray>("KEY_VALUES", "([Ljava/lang/String;)V",
+ obj.setObjectField<jobjectArray>("KEY_VALUES", "([Ljava/lang/String;)V",
stringArray.object<jobjectArray>())
\endcode
*/
-template <> Q_CORE_EXPORT
-void QJniObject::setField<jobject>(const char *fieldName, const char *signature, jobject value)
-{
- QJniEnvironment env;
- jfieldID id = getCachedFieldID(env.jniEnv(), d->m_jclass, d->m_className, fieldName, signature);
- if (id) {
- env->SetObjectField(d->m_jobject, id, value);
- env.checkAndClearExceptions();
- }
-}
-
-template <> Q_CORE_EXPORT
-void QJniObject::setField<jobjectArray>(const char *fieldName,
- const char *signature,
- jobjectArray value)
-{
- QJniEnvironment env;
- jfieldID id = getCachedFieldID(env.jniEnv(), d->m_jclass, d->m_className, fieldName, signature);
- if (id) {
- env->SetObjectField(d->m_jobject, id, value);
- env.checkAndClearExceptions();
- }
-}
/*!
\fn QJniObject QJniObject::getObjectField(const char *fieldName) const
@@ -1672,7 +1209,7 @@ void QJniObject::setField<jobjectArray>(const char *fieldName,
QJniObject QJniObject::getObjectField(const char *fieldName, const char *signature) const
{
QJniEnvironment env;
- jfieldID id = getCachedFieldID(env.jniEnv(), d->m_jclass, d->m_className, fieldName, signature);
+ jfieldID id = getCachedFieldID(env.jniEnv(), fieldName, signature);
if (!id)
return QJniObject();
@@ -1712,52 +1249,6 @@ QJniObject QJniObject::getObjectField(const char *fieldName, const char *signatu
\endcode
*/
-#define MAKE_JNI_OBJECT_FILEDS(Type, Signature) \
-template <> Q_CORE_EXPORT void QJniObject::setField<Type>(const char *fieldName, Type value) \
-{ \
- QJniObject::setField<jobject>(fieldName, Signature, value); \
-} \
-\
-template <> Q_CORE_EXPORT void QJniObject::setStaticField<Type>(const char *className, \
- const char *fieldName, \
- Type value) \
-{ \
- QJniObject::setStaticField<jobject>(className, fieldName, Signature, value); \
-}\
-template <>\
-Q_CORE_EXPORT QJniObject QJniObject::getObjectField<Type>(const char *fieldName) const\
-{\
- return getObjectField(fieldName, Signature);\
-}\
-template <>\
-Q_CORE_EXPORT QJniObject QJniObject::getStaticObjectField<Type>(jclass clazz,\
- const char *fieldName)\
-{\
- return getStaticObjectField(clazz, fieldName, Signature);\
-}\
-template <>\
-Q_CORE_EXPORT QJniObject QJniObject::getStaticObjectField<Type>(const char *className,\
- const char *fieldName)\
-{\
- return getStaticObjectField(className, fieldName, Signature);\
-}\
-
-#define DECLARE_JNI_OBJECT_FILEDS(Type, Signature) MAKE_JNI_OBJECT_FILEDS(Type, Signature)
-
-DECLARE_JNI_OBJECT_FILEDS(jobject, "Ljava/lang/Object;")
-DECLARE_JNI_OBJECT_FILEDS(jobjectArray, "[Ljava/lang/Object;")
-DECLARE_JNI_OBJECT_FILEDS(jstring, "Ljava/lang/String;")
-DECLARE_JNI_OBJECT_FILEDS(jclass, "Ljava/lang/Class;")
-DECLARE_JNI_OBJECT_FILEDS(jthrowable, "Ljava/lang/Throwable;")
-DECLARE_JNI_OBJECT_FILEDS(jbooleanArray, "[Z")
-DECLARE_JNI_OBJECT_FILEDS(jbyteArray, "[B")
-DECLARE_JNI_OBJECT_FILEDS(jcharArray, "[C")
-DECLARE_JNI_OBJECT_FILEDS(jshortArray, "[S")
-DECLARE_JNI_OBJECT_FILEDS(jintArray, "[I")
-DECLARE_JNI_OBJECT_FILEDS(jlongArray, "[J")
-DECLARE_JNI_OBJECT_FILEDS(jfloatArray, "[F")
-DECLARE_JNI_OBJECT_FILEDS(jdoubleArray, "[D")
-
/*!
\fn QJniObject QJniObject::fromString(const QString &string)
diff --git a/src/corelib/kernel/qjniobject.h b/src/corelib/kernel/qjniobject.h
index 0f88695e73..83d64ad485 100644
--- a/src/corelib/kernel/qjniobject.h
+++ b/src/corelib/kernel/qjniobject.h
@@ -40,14 +40,11 @@
#ifndef QJNIOBJECT_H
#define QJNIOBJECT_H
-#include <QtCore/QSharedPointer>
+#include <QtCore/qsharedpointer.h>
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
#include <jni.h>
-#else
-class jclass;
-class jobject;
-#endif
+#include <QtCore/qjnienvironment.h>
QT_BEGIN_NAMESPACE
@@ -64,85 +61,375 @@ public:
QJniObject(jobject globalRef);
~QJniObject();
- template <typename T>
- T object() const;
jobject object() const;
+ template <typename T> T object() const
+ {
+ assertJniObjectType<T>();
+ return static_cast<T>(javaObject());
+ }
template <typename T>
- T callMethod(const char *methodName, const char *signature, ...) const;
+ T callMethod(const char *methodName, const char *signature, ...) const
+ {
+ 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;
+ }
+
+ 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();
+ }
+ }
+
template <typename T>
- T callMethod(const char *methodName) const;
+ T callMethod(const char *methodName) const
+ {
+ assertJniPrimitiveType<T>();
+ constexpr const char *signature = getTypeSignature<T>();
+ return callMethod<T>(methodName, QByteArray(signature).prepend("()").constData());
+ }
+
+ template <>
+ void callMethod<void>(const char *methodName) const
+ {
+ callMethod<void>(methodName, "()V");
+ }
+
template <typename T>
- QJniObject callObjectMethod(const char *methodName) const;
+ QJniObject callObjectMethod(const char *methodName) const
+ {
+ assertJniObjectType<T>();
+ constexpr const char *signature = getTypeSignature<T>();
+ return callObjectMethod(methodName, QByteArray(signature).prepend("()").constData());
+ }
+
QJniObject callObjectMethod(const char *methodName, const char *signature, ...) const;
template <typename T>
static T callStaticMethod(const char *className, const char *methodName,
- const char *signature, ...);
- 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;
+ }
+
+ 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);
+ if (id) {
+ va_list args;
+ va_start(args, signature);
+ env->CallStaticVoidMethodV(clazz, id, args);
+ va_end(args);
+ env.checkAndClearExceptions();
+ }
+ }
+ }
+
template <typename T>
- static T callStaticMethod(jclass clazz, const char *methodName, const char *signature, ...);
+ static T callStaticMethod(const char *className, const char *methodName)
+ {
+ assertJniPrimitiveType<T>();
+ constexpr const char *signature = getTypeSignature<T>();
+ return callStaticMethod<T>(className, methodName, QByteArray(signature).prepend("()").constData());
+ }
+
+ template <>
+ void callStaticMethod<void>(const char *className, const char *methodName)
+ {
+ callStaticMethod<void>(className, methodName, "()V");
+ }
+
template <typename T>
- static T callStaticMethod(jclass clazz, const char *methodName);
+ 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;
+ }
+
+ template <>
+ void callStaticMethod<void>(jclass clazz, const char *methodName,
+ const char *signature, ...)
+ {
+ 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();
+ }
+ }
+ }
+
+ template <typename T> static T callStaticMethod(jclass clazz, const char *methodName)
+ {
+ assertJniPrimitiveType<T>();
+ constexpr const char *signature = getTypeSignature<T>();
+ return callStaticMethod<T>(clazz, methodName, QByteArray(signature).prepend("()").constData());
+ }
+
+ template <>
+ void callStaticMethod<void>(jclass clazz, const char *methodName)
+ {
+ callStaticMethod<void>(clazz, methodName, "()V");
+ }
template <typename T>
- static QJniObject callStaticObjectMethod(const char *className, const char *methodName);
- static QJniObject callStaticObjectMethod(const char *className,
- const char *methodName,
+ static QJniObject callStaticObjectMethod(const char *className, const char *methodName)
+ {
+ assertJniObjectType<T>();
+ constexpr const char *signature = getTypeSignature<T>();
+ return callStaticObjectMethod(className, methodName, QByteArray(signature).prepend("()").constData());
+ }
+
+ static QJniObject callStaticObjectMethod(const char *className, const char *methodName,
const char *signature, ...);
template <typename T>
- static QJniObject callStaticObjectMethod(jclass clazz, const char *methodName);
- static QJniObject callStaticObjectMethod(jclass clazz,
- const char *methodName,
+ 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, ...);
- template <typename T>
- T getField(const char *fieldName) const;
+ template <typename T> T getField(const char *fieldName) const
+ {
+ 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;
+ }
template <typename T>
- static T getStaticField(const char *className, const char *fieldName);
+ static T getStaticField(const char *className, const char *fieldName)
+ {
+ assertJniPrimitiveType<T>();
+ QJniEnvironment env;
+ jclass clazz = QJniObject::loadClass(className, env.jniEnv());
+ if (!clazz)
+ return 0;
+
+ constexpr const char *signature = getTypeSignature<T>();
+ jfieldID id = getCachedFieldID(env.jniEnv(), clazz,
+ QJniObject::toBinaryEncClassName(className),
+ fieldName,
+ signature, true);
+ if (!id)
+ return 0;
+
+ T res{};
+ getStaticFieldForType<T>(env.jniEnv(), res, clazz, id);
+ if (env.checkAndClearExceptions())
+ res = {};
+ return res;
+ }
+
template <typename T>
- static T getStaticField(jclass clazz, const char *fieldName);
+ 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 = {};
+ }
+ return res;
+ }
template <typename T>
- QJniObject getObjectField(const char *fieldName) const;
+ QJniObject getObjectField(const char *fieldName) const
+ {
+ assertJniObjectType<T>();
+ constexpr const char *signature = getTypeSignature<T>();
+ return getObjectField(fieldName, signature);
+ }
+
QJniObject getObjectField(const char *fieldName, const char *signature) const;
template <typename T>
- static QJniObject getStaticObjectField(const char *className, const char *fieldName);
- static QJniObject getStaticObjectField(const char *className,
- const char *fieldName,
- const char *signature);
- template <typename T>
+ static QJniObject getStaticObjectField(const char *className, const char *fieldName)
+ {
+ assertJniObjectType<T>();
+ constexpr const char *signature = getTypeSignature<T>();
+ return getStaticObjectField(className, fieldName, signature);
+ }
+
static QJniObject getStaticObjectField(const char *className,
const char *fieldName,
const char *signature);
template <typename T>
- static QJniObject getStaticObjectField(jclass clazz, const char *fieldName);
- static QJniObject getStaticObjectField(jclass clazz, const char *fieldName,
- const char *signature);
- template <typename T>
+ static QJniObject getStaticObjectField(jclass clazz, const char *fieldName)
+ {
+ assertJniObjectType<T>();
+ constexpr const char *signature = getTypeSignature<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)
+ {
+ assertJniType<T>();
+ QJniEnvironment env;
+ constexpr const char *signature = getTypeSignature<T>();
+ jfieldID id = getCachedFieldID(env.jniEnv(), fieldName, signature);
+ if (id) {
+ setFieldForType<T>(env, object(), id, value);
+ env.checkAndClearExceptions();
+ }
+ }
+
template <typename T>
- void setField(const char *fieldName, T value);
- template <typename T>
- void setField(const char *fieldName, const char *signature, T value);
+ void setField(const char *fieldName, const char *signature, T value)
+ {
+ assertJniType<T>();
+ QJniEnvironment env;
+ jfieldID id = getCachedFieldID(env.jniEnv(), fieldName, signature);
+ if (id) {
+ setFieldForType<T>(env, object(), id, value);
+ env.checkAndClearExceptions();
+ }
+ }
+
template <typename T>
- static void setStaticField(const char *className, const char *fieldName, T value);
+ static void setStaticField(const char *className, const char *fieldName, T value)
+ {
+ assertJniType<T>();
+ QJniEnvironment env;
+ jclass clazz = QJniObject::loadClass(className, env.jniEnv());
+ if (!clazz)
+ return;
+
+ constexpr const char *signature = getTypeSignature<T>();
+ jfieldID id = getCachedFieldID(env.jniEnv(), clazz, className, fieldName,
+ signature, true);
+ if (!id)
+ return;
+
+ setStaticFieldForType<T>(env, clazz, id, value);
+ env.checkAndClearExceptions();
+ }
+
template <typename T>
static void setStaticField(const char *className, const char *fieldName,
- const char *signature, T value);
+ const char *signature, T value)
+ {
+ assertJniType<T>();
+ QJniEnvironment env;
+ jclass clazz = QJniObject::loadClass(className, env.jniEnv());
+
+ if (!clazz)
+ return;
+
+ jfieldID id = getCachedFieldID(env.jniEnv(), clazz, className, fieldName,
+ signature, true);
+ if (id) {
+ setStaticFieldForType<T>(env, clazz, id, value);
+ env.checkAndClearExceptions();
+ }
+ }
+
template <typename T>
static void setStaticField(jclass clazz, const char *fieldName,
- const char *signature, T value);
+ const char *signature, T value)
+ {
+ assertJniType<T>();
+ QJniEnvironment env;
+ jfieldID id = getFieldID(env.jniEnv(), clazz, fieldName, signature, true);
+
+ if (id) {
+ setStaticFieldForType<T>(env, clazz, id, value);
+ env.checkAndClearExceptions();
+ }
+ }
template <typename T>
- static void setStaticField(jclass clazz, const char *fieldName, T value);
+ 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, clazz, id, value);
+ env.checkAndClearExceptions();
+ }
+ }
static QJniObject fromString(const QString &string);
QString toString() const;
@@ -153,39 +440,47 @@ 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> QJniObject &operator=(T obj)
+ {
+ assertJniType<T>();
+ assign(static_cast<T>(obj));
+ return *this;
+ }
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);
- template <typename T>
- T callMethodV(const char *methodName, const char *signature, va_list args) const;
- QJniObject callObjectMethodV(const char *methodName,
- const char *signature,
+ static jclass loadClass(const QByteArray &className, JNIEnv *env, bool binEncoded = false);
+ static QByteArray toBinaryEncClassName(const QByteArray &className);
+ static QJniObject getCleanJniObject(jobject obj);
+
+ static jfieldID getCachedFieldID(JNIEnv *env, jclass clazz, const QByteArray &className,
+ const char *name, const char *signature,
+ bool isStatic = false);
+ jfieldID getCachedFieldID(JNIEnv *env, const char *name, const char *signature,
+ bool isStatic = false) const;
+ static jmethodID getCachedMethodID(JNIEnv *env, jclass clazz, const QByteArray &className,
+ const char *name, const char *signature,
+ bool isStatic = false);
+ jmethodID getCachedMethodID(JNIEnv *env, const char *name, const char *signature,
+ bool isStatic = false) const;
+
+ static jfieldID getFieldID(JNIEnv *env, jclass clazz, const char *name,
+ const char *signature, bool isStatic = false);
+ 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;
- template <typename T>
- static T callStaticMethodV(const char *className,
- const char *methodName,
- const char *signature,
- va_list args);
- template <typename T>
- static T callStaticMethodV(jclass clazz,
- const char *methodName,
- const char *signature,
- va_list args);
- static QJniObject callStaticObjectMethodV(const char *className,
- const char *methodName,
- const char *signature,
- va_list args);
+ 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);
+ static QJniObject callStaticObjectMethodV(jclass clazz, const char *methodName,
+ const char *signature, va_list args);
bool isSameObject(jobject obj) const;
bool isSameObject(const QJniObject &other) const;
@@ -195,6 +490,249 @@ private:
friend bool operator==(const QJniObject &, const QJniObject &);
friend bool operator!=(const QJniObject&, const QJniObject&);
+ template<bool flag = false>
+ static void staticAssertTypeMismatch()
+ {
+ static_assert(flag, "The used type is not supported by this template call. "
+ "Use a JNI based type instead.");
+ }
+
+ 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;
+ }
+
+ return true;
+ }
+
+ template<typename T>
+ static constexpr void assertJniPrimitiveType()
+ {
+ if constexpr(!isJniPrimitiveType<T>())
+ staticAssertTypeMismatch();
+ }
+
+ template<typename T>
+ static constexpr void assertJniObjectType()
+ {
+ if constexpr(!std::is_convertible<T, jobject>::value)
+ staticAssertTypeMismatch();
+ }
+
+ template<typename T>
+ static constexpr void assertJniType()
+ {
+ if constexpr(!isJniPrimitiveType<T>() && !std::is_convertible<T, jobject>::value)
+ staticAssertTypeMismatch();
+ }
+
+ 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();
+ }
+
+ 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();
+ }
+
+ 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();
+ }
+
+ 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();
+ }
+
+ 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();
+ }
+
+ 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>
+ 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();
+ }
+
+ friend QJniObjectPrivate;
QSharedPointer<QJniObjectPrivate> d;
};
@@ -210,4 +748,6 @@ inline bool operator!=(const QJniObject &obj1, const QJniObject &obj2)
QT_END_NAMESPACE
+#endif
+
#endif // QJNIOBJECT_H
diff --git a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp
index 96637a72a6..7b5c60a7d7 100644
--- a/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp
+++ b/tests/auto/corelib/kernel/qjniobject/tst_qjniobject.cpp
@@ -26,6 +26,8 @@
**
****************************************************************************/
+#include <jni.h>
+
#include <QString>
#include <QtCore/QJniEnvironment>
#include <QtCore/QJniObject>
@@ -520,9 +522,9 @@ void tst_QJniObject::callStaticLongMethod()
void tst_QJniObject::getStaticObjectFieldClassName()
{
{
- QJniObject boolObject = QJniObject::getStaticObjectField<jobject>("java/lang/Boolean",
- "FALSE",
- "Ljava/lang/Boolean;");
+ QJniObject boolObject = QJniObject::getStaticObjectField("java/lang/Boolean",
+ "FALSE",
+ "Ljava/lang/Boolean;");
QVERIFY(boolObject.isValid());
jboolean booleanValue = boolObject.callMethod<jboolean>("booleanValue");
@@ -530,9 +532,9 @@ void tst_QJniObject::getStaticObjectFieldClassName()
}
{
- QJniObject boolObject = QJniObject::getStaticObjectField<jobject>("java/lang/Boolean",
- "TRUE",
- "Ljava/lang/Boolean;");
+ QJniObject boolObject = QJniObject::getStaticObjectField("java/lang/Boolean",
+ "TRUE",
+ "Ljava/lang/Boolean;");
QVERIFY(boolObject.isValid());
jboolean booleanValue = boolObject.callMethod<jboolean>("booleanValue");
@@ -556,9 +558,9 @@ void tst_QJniObject::getStaticObjectField()
QVERIFY(cls != 0);
{
- QJniObject boolObject = QJniObject::getStaticObjectField<jobject>(cls,
- "FALSE",
- "Ljava/lang/Boolean;");
+ QJniObject boolObject = QJniObject::getStaticObjectField(cls,
+ "FALSE",
+ "Ljava/lang/Boolean;");
QVERIFY(boolObject.isValid());
jboolean booleanValue = boolObject.callMethod<jboolean>("booleanValue");
@@ -566,9 +568,9 @@ void tst_QJniObject::getStaticObjectField()
}
{
- QJniObject boolObject = QJniObject::getStaticObjectField<jobject>(cls,
- "TRUE",
- "Ljava/lang/Boolean;");
+ QJniObject boolObject = QJniObject::getStaticObjectField(cls,
+ "TRUE",
+ "Ljava/lang/Boolean;");
QVERIFY(boolObject.isValid());
jboolean booleanValue = boolObject.callMethod<jboolean>("booleanValue");