summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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");