summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/kernel/qjnienvironment.cpp51
-rw-r--r--src/corelib/kernel/qjnienvironment.h21
-rw-r--r--src/corelib/kernel/qjniobject.cpp151
-rw-r--r--src/corelib/kernel/qjniobject.h269
4 files changed, 301 insertions, 191 deletions
diff --git a/src/corelib/kernel/qjnienvironment.cpp b/src/corelib/kernel/qjnienvironment.cpp
index 9766ff4d3b9..3eab31bbc26 100644
--- a/src/corelib/kernel/qjnienvironment.cpp
+++ b/src/corelib/kernel/qjnienvironment.cpp
@@ -232,6 +232,16 @@ jmethodID QJniEnvironment::findMethod(jclass clazz, const char *methodName, cons
}
/*!
+ \fn template<typename ...Args> jmethodId QJniEnvironment::findMethod(jclass clazz, const char *methodName)
+ \since 6.4
+
+ Searches for an instance method of a class \a clazz. The method is specified
+ by its \a methodName, the signature is deduced from the template parameters.
+
+ Returns the method ID or \c nullptr if the method is not found.
+*/
+
+/*!
Searches for a static method of a class \a clazz. The method is specified
by its \a methodName and \a signature.
@@ -265,9 +275,28 @@ jmethodID QJniEnvironment::findStaticMethod(jclass clazz, const char *methodName
return nullptr;
}
+/*!
+ \fn template<typename ...Args> jmethodId QJniEnvironment::findStaticMethod(jclass clazz, const char *methodName)
+ \since 6.4
+
+ Searches for an instance method of a class \a clazz. The method is specified
+ by its \a methodName, the signature is deduced from the template parameters.
+
+ Returns the method ID or \c nullptr if the method is not found.
+
+ \code
+ QJniEnvironment env;
+ jclass javaClass = env.findClass("org/qtproject/example/android/CustomClass");
+ jmethodID methodId = env.findStaticMethod<void, jstring>(javaClass, "staticJavaMethod");
+ QJniObject javaMessage = QJniObject::fromString("findStaticMethod example");
+ QJniObject::callStaticMethod<void>(javaClass,
+ methodId,
+ javaMessage.object<jstring>());
+ \endcode
+*/
/*!
- Searches for an member field of a class \a clazz. The field is specified
+ Searches for a member field of a class \a clazz. The field is specified
by its \a fieldName and \a signature.
Returns the field ID or \c nullptr if the field is not found.
@@ -289,6 +318,16 @@ jfieldID QJniEnvironment::findField(jclass clazz, const char *fieldName, const c
}
/*!
+ \fn template<typename T> jfieldID QJniEnvironment::findField(jclass clazz, const char *fieldName)
+ \since 6.4
+
+ Searches for a member field of a class \a clazz. The field is specified
+ by its \a fieldName. The signature of the field is deduced from the template parameter.
+
+ Returns the field ID or \c nullptr if the field is not found.
+*/
+
+/*!
Searches for a static field of a class \a clazz. The field is specified
by its \a fieldName and \a signature.
@@ -311,6 +350,16 @@ jfieldID QJniEnvironment::findStaticField(jclass clazz, const char *fieldName, c
}
/*!
+ \fn template<typename T> jfieldID QJniEnvironment::findStaticField(jclass clazz, const char *fieldName)
+ \since 6.4
+
+ Searches for a static field of a class \a clazz. The field is specified
+ by its \a fieldName. The signature of the field is deduced from the template parameter.
+
+ Returns the field ID or \c nullptr if the field is not found.
+*/
+
+/*!
\fn JavaVM *QJniEnvironment::javaVM()
Returns the Java VM interface for the current process. Although it might
diff --git a/src/corelib/kernel/qjnienvironment.h b/src/corelib/kernel/qjnienvironment.h
index 16a6413d318..8263d04834d 100644
--- a/src/corelib/kernel/qjnienvironment.h
+++ b/src/corelib/kernel/qjnienvironment.h
@@ -44,6 +44,7 @@
#if defined(Q_QDOC) || defined(Q_OS_ANDROID)
#include <jni.h>
+#include <QtCore/qjnitypes.h>
QT_BEGIN_NAMESPACE
@@ -60,9 +61,29 @@ public:
JNIEnv *jniEnv() const;
jclass findClass(const char *className);
jmethodID findMethod(jclass clazz, const char *methodName, const char *signature);
+ template<typename ...Args>
+ jmethodID findMethod(jclass clazz, const char *methodName) {
+ constexpr auto signature = QtJniTypes::methodSignature<Args...>();
+ return findMethod(clazz, methodName, signature.data());
+ }
jmethodID findStaticMethod(jclass clazz, const char *methodName, const char *signature);
+ template<typename ...Args>
+ jmethodID findStaticMethod(jclass clazz, const char *methodName) {
+ constexpr auto signature = QtJniTypes::methodSignature<Args...>();
+ return findStaticMethod(clazz, methodName, signature.data());
+ }
jfieldID findField(jclass clazz, const char *fieldName, const char *signature);
+ template<typename T>
+ jfieldID findField(jclass clazz, const char *fieldName) {
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
+ return findField(clazz, fieldName, signature.data());
+ }
jfieldID findStaticField(jclass clazz, const char *fieldName, const char *signature);
+ template<typename T>
+ jfieldID findStaticField(jclass clazz, const char *fieldName) {
+ constexpr auto signature = QtJniTypes::fieldSignature<T>();
+ return findStaticField(clazz, fieldName, signature.data());
+ }
static JavaVM *javaVM();
bool registerNativeMethods(const char *className, const JNINativeMethod methods[], int size);
bool registerNativeMethods(jclass clazz, const JNINativeMethod methods[], int size);
diff --git a/src/corelib/kernel/qjniobject.cpp b/src/corelib/kernel/qjniobject.cpp
index fcc4851c74c..e801aa958f3 100644
--- a/src/corelib/kernel/qjniobject.cpp
+++ b/src/corelib/kernel/qjniobject.cpp
@@ -76,55 +76,77 @@ using namespace Qt::StringLiterals;
\section1 Method Signatures
- For functions that take no arguments, QJniObject provides convenience functions that will use
- the correct signature based on the provided template type. For example:
+ QJniObject provides convenience functions that will use the correct signature based on the
+ provided template types. For functions that only return and take \l {JNI types}, the
+ signature can be generate at compile time:
\code
jint x = QJniObject::callMethod<jint>("getSize");
QJniObject::callMethod<void>("touch");
+ jint ret = jString1.callMethod<jint>("compareToIgnoreCase", jString2.object<jstring>());
\endcode
- In other cases you will need to supply the signature yourself, and it is important that the
- signature matches the function you want to call. The signature structure is
- \c "(ArgumentsTypes)ReturnType". Array types in the signature must have the \c {[} prefix,
- and the fully-qualified \c Object type names must have the \c L prefix and the \c ; suffix.
+ These functions are variadic templates, and the compiler will deduce the template arguments
+ from the actual argument types. In many situations, only the return type needs to be provided
+ explicitly.
- The example below demonstrates how to call two different static functions:
+ For functions that take other argument types, you need to supply the signature yourself. It is
+ important that the signature matches the function you want to call. The example below
+ demonstrates how to call different static functions:
\code
// Java class
package org.qtproject.qt;
class TestClass
{
- static String fromNumber(int x) { ... }
- static String[] stringArray(String s1, String s2) { ... }
+ static TestClass create() { ... }
+ static String fromNumber(int x) { ... }
+ static String[] stringArray(String s1, String s2) { ... }
}
\endcode
- The signature for the first function is \c {"(I)Ljava/lang/String;"}:
+ The signature structure is \c "(ArgumentsTypes)ReturnType". Array types in the signature
+ must have the \c {[} prefix, and the fully-qualified \c Object type names must have the
+ \c L prefix and the \c ; suffix. The signature for the \c create function is
+ \c {"()Lorg/qtproject/qt/TestClass;}. The signatures for the second and third functions
+ are \c {"(I)Ljava/lang/String;"} and
+ \c {"(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"}, respectively.
+
+ We can call the \c create() function like this:
+
+ \code
+ // C++ code
+ QJniObject testClass = QJniObject::callStaticObjectMethod("org/qtproject/qt/TestClass",
+ "create",
+ "()Lorg/qtproject/qt/TestClass;");
+ \endcode
+
+ For the second and third function we can rely on QJniObject's template methods to create
+ the implicit signature string, but we can also pass the signature string explicitly:
\code
// C++ code
QJniObject stringNumber = QJniObject::callStaticObjectMethod("org/qtproject/qt/TestClass",
- "fromNumber"
- "(I)Ljava/lang/String;",
- 10);
+ "fromNumber",
+ "(I)Ljava/lang/String;", 10);
\endcode
- and the signature for the second function is
- \c {"(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"}:
+ For the implicit signature creation to work we need to specify the return type explicitly:
\code
// C++ code
QJniObject string1 = QJniObject::fromString("String1");
QJniObject string2 = QJniObject::fromString("String2");
- QJniObject stringArray = QJniObject::callStaticObjectMethod("org/qtproject/qt/TestClass",
+ QJniObject stringArray = QJniObject::callStaticObjectMethod<jstringArray>(
+ "org/qtproject/qt/TestClass",
"stringArray"
- "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"
string1.object<jstring>(),
string2.object<jstring>());
\endcode
+ Note that while he first template parameter specifies the return type of the Java
+ function, the method will still return a QJniObject.
+
\section1 Handling Java Exception
After calling Java functions that might throw exceptions, it is important
@@ -403,9 +425,12 @@ jmethodID QJniObject::getMethodID(JNIEnv *env,
return id;
}
-void QJniObject::callVoidMethodV(JNIEnv *env, jmethodID id, va_list args) const
+void QJniObject::callVoidMethodV(JNIEnv *env, jmethodID id, ...) const
{
+ va_list args;
+ va_start(args, id);
env->CallVoidMethodV(d->m_jobject, id, args);
+ va_end(args);
}
jmethodID QJniObject::getCachedMethodID(JNIEnv *env,
@@ -620,6 +645,22 @@ QJniObject::QJniObject(const char *className, const char *signature, ...)
}
}
+/*!
+ \fn template<typename ...Args> QJniObject::QJniObject(const char *className, Args &&...args)
+ \since 6.4
+
+ Constructs a new JNI object by calling the constructor of \a className with
+ the arguments \a args. This constructor is only available if all \a args are
+ known \l {JNI Types}.
+
+ \code
+ QJniEnvironment env;
+ char* str = "Hello";
+ jstring myJStringArg = env->NewStringUTF(str);
+ QJniObject myNewJavaString("java/lang/String", myJStringArg);
+ \endcode
+*/
+
QJniObject::QJniObject(const char *className, const char *signature, const QVaListPrivate &args)
: d(new QJniObjectPrivate())
{
@@ -672,6 +713,21 @@ QJniObject::QJniObject(jclass clazz, const char *signature, ...)
}
/*!
+ \fn template<typename ...Args> QJniObject::QJniObject(jclass clazz, Args &&...args)
+ \since 6.4
+
+ Constructs a new JNI object from \a clazz by calling the constructor with
+ the arguments \a args. This constructor is only available if all \a args are
+ known \l {JNI Types}.
+
+ \code
+ QJniEnvironment env;
+ jclass myClazz = env.findClass("org/qtproject/qt/TestClass");
+ QJniObject(myClazz, 3);
+ \endcode
+*/
+
+/*!
Constructs a new JNI object by calling the default constructor of \a clazz.
\note The QJniObject will create a new reference to the class \a clazz
@@ -883,10 +939,11 @@ QJniObject QJniObject::callStaticObjectMethodV(jclass clazz,
}
/*!
- \fn template <typename T> T QJniObject::callMethod(const char *methodName, const char *signature, ...) const
+ \fn template <typename Ret, typename ...Args> Ret QJniObject::callMethod(const char *methodName, const char *signature, Args &&...args) const
+ \since 6.4
Calls the object's method \a methodName with \a signature specifying the types of any
- subsequent arguments.
+ subsequent arguments \a args.
\code
QJniObject myJavaStrin("org/qtproject/qt/TestClass");
@@ -896,21 +953,25 @@ QJniObject QJniObject::callStaticObjectMethodV(jclass clazz,
*/
/*!
- \fn template <typename T> T QJniObject::callMethod(const char *methodName) const
+ \fn template <typename Ret, typename ...Args> Ret QJniObject::callMethod(const char *methodName, Args &&...args) const
+ \since 6.4
- Calls the method \a methodName and returns the value.
+ Calls the method \a methodName with arguments \a args and returns the value.
\code
QJniObject myJavaStrin("org/qtproject/qt/TestClass");
jint size = myJavaString.callMethod<jint>("length");
\endcode
+
+ The method signature is deduced at compile time from \c Ret and the types of \a args.
*/
/*!
- \fn template <typename T> T QJniObject::callStaticMethod(const char *className, const char *methodName, const char *signature, ...)
+ \fn template <typename Ret, typename ...Args> Ret QJniObject::callStaticMethod(const char *className, const char *methodName, const char *signature, Args &&...args)
+ \since 6.4
Calls the static method \a methodName from class \a className with \a signature
- specifying the types of any subsequent arguments.
+ specifying the types of any subsequent arguments \a args.
\code
jint a = 2;
@@ -920,17 +981,21 @@ QJniObject QJniObject::callStaticObjectMethodV(jclass clazz,
*/
/*!
- \fn template <typename T> T QJniObject::callStaticMethod(const char *className, const char *methodName)
+ \fn template <typename Ret, typename ...Args> Ret QJniObject::callStaticMethod(const char *className, const char *methodName, Args &&...args)
+ \since 6.4
- Calls the static method \a methodName on class \a className and returns the value.
+ Calls the static method \a methodName on class \a className with arguments \a args,
+ and returns the value of type \c Ret.
\code
jint value = QJniObject::callStaticMethod<jint>("MyClass", "staticMethod");
\endcode
+
+ The method signature is deduced at compile time from \c Ret and the types of \a args.
*/
/*!
- \fn template <typename T> T QJniObject::callStaticMethod(jclass clazz, const char *methodName, const char *signature, ...)
+ \fn template <typename Ret, typename ...Args> Ret QJniObject::callStaticMethod(jclass clazz, const char *methodName, const char *signature, Args &&...args)
Calls the static method \a methodName from \a clazz with \a signature
specifying the types of any subsequent arguments.
@@ -945,7 +1010,8 @@ QJniObject QJniObject::callStaticObjectMethodV(jclass clazz,
*/
/*!
- \fn template <typename T> T QJniObject::callStaticMethod(jclass clazz, jmethodID methodId, ...)
+ \fn template <typename Ret, typename ...Args> Ret QJniObject::callStaticMethod(jclass clazz, jmethodID methodId, Args &&...args)
+ \since 6.4
Calls the static method identified by \a methodId from the class \a clazz
with any subsequent arguments. Useful when \a clazz and \a methodId are
@@ -964,7 +1030,8 @@ QJniObject QJniObject::callStaticObjectMethodV(jclass clazz,
*/
/*!
- \fn template <typename T> T QJniObject::callStaticMethod(jclass clazz, const char *methodName)
+ \fn template <typename Ret, typename ...Args> Ret QJniObject::callStaticMethod(jclass clazz, const char *methodName, Args &&...args)
+ \since 6.4
Calls the static method \a methodName on \a clazz and returns the value.
@@ -973,6 +1040,8 @@ QJniObject QJniObject::callStaticObjectMethodV(jclass clazz,
jclass javaMathClass = env.findClass("java/lang/Math");
jdouble randNr = QJniObject::callStaticMethod<jdouble>(javaMathClass, "random");
\endcode
+
+ The method signature is deduced at compile time from \c Ret and the types of \a args.
*/
/*!
@@ -1090,32 +1159,40 @@ QJniObject QJniObject::callStaticObjectMethod(jclass clazz, jmethodID methodId,
}
/*!
- \fn QJniObject QJniObject::callObjectMethod(const char *methodName) const
+ \fn template<typename Ret, typename ...Args> QJniObject QJniObject::callObjectMethod(const char *methodName, Args &&...args) const
+ \since 6.4
- Calls the Java objects method \a methodName and returns a new QJniObject for
- the returned Java object.
+ Calls the Java objects method \a methodName with arguments \a args and returns a
+ new QJniObject for the returned Java object.
\code
QJniObject myJavaString = QJniObject::fromString("Hello, Java");
QJniObject myJavaString2 = myJavaString1.callObjectMethod<jstring>("toString");
\endcode
+
+ The method signature is deduced at compile time from \c Ret and the types of \a args.
*/
/*!
- \fn QJniObject QJniObject::callStaticObjectMethod(const char *className, const char *methodName)
+ \fn template<typename Ret, typename ...Args> QJniObject QJniObject::callStaticObjectMethod(const char *className, const char *methodName, Args &&...args)
+ \since 6.4
- Calls the static method with \a methodName on the class \a className.
+ Calls the static method with \a methodName on the class \a className, passing
+ arguments \a args, and returns a new QJniObject for the returned Java object.
\code
QJniObject string = QJniObject::callStaticObjectMethod<jstring>("CustomClass", "getClassName");
\endcode
+
+ The method signature is deduced at compile time from \c Ret and the types of \a args.
*/
/*!
- \fn QJniObject QJniObject::callStaticObjectMethod(jclass clazz, const char *methodName)
-
- Calls the static method with \a methodName on \a clazz.
+ \fn template<typename Ret, typename ...Args> QJniObject QJniObject::callStaticObjectMethod(jclass clazz, const char *methodName, Args &&...args)
+ \since 6.4
+ Calls the static method with \a methodName on \a clazz, passing arguments \a args,
+ and returns a new QJniObject for the returned Java object.
*/
/*!
diff --git a/src/corelib/kernel/qjniobject.h b/src/corelib/kernel/qjniobject.h
index 829823efecf..56700ddcbfa 100644
--- a/src/corelib/kernel/qjniobject.h
+++ b/src/corelib/kernel/qjniobject.h
@@ -57,8 +57,26 @@ public:
QJniObject();
explicit QJniObject(const char *className);
explicit QJniObject(const char *className, const char *signature, ...);
+ template<typename ...Args
+#ifndef Q_QDOC
+ , std::enable_if_t<!std::disjunction_v<QtJniTypes::IsStringType<std::decay_t<Args>>...>>* = nullptr
+#endif
+ >
+ explicit QJniObject(const char *className, Args &&...args)
+ : QJniObject(className, QtJniTypes::constructorSignature<Args...>().data(),
+ std::forward<Args>(args)...)
+ {}
explicit QJniObject(jclass clazz);
explicit QJniObject(jclass clazz, const char *signature, ...);
+ template<typename ...Args
+#ifndef Q_QDOC
+ , std::enable_if_t<!std::disjunction_v<QtJniTypes::IsStringType<std::decay_t<Args>>...>>* = nullptr
+#endif
+ >
+ explicit QJniObject(jclass clazz, Args &&...args)
+ : QJniObject(clazz, QtJniTypes::constructorSignature<Args...>().data(),
+ std::forward<Args>(args)...)
+ {}
QJniObject(jobject globalRef);
~QJniObject();
@@ -72,206 +90,135 @@ public:
jclass objectClass() const;
QByteArray className() const;
- template <typename T>
- T callMethod(const char *methodName, const char *signature, ...) const
+ template <typename Ret, typename ...Args>
+ Ret callMethod(const char *methodName, const char *signature, Args &&...args) const
{
- QtJniTypes::assertPrimitiveType<T>();
+ QtJniTypes::assertPrimitiveType<Ret>();
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 = {};
+ if constexpr (std::is_same<Ret, void>::value) {
+ callVoidMethodV(env.jniEnv(), id, std::forward<Args>(args)...);
+ env.checkAndClearExceptions();
+ } else {
+ Ret res{};
+ callMethodForType<Ret>(env.jniEnv(), res, object(), id, std::forward<Args>(args)...);
+ if (env.checkAndClearExceptions())
+ res = {};
+ return res;
+ }
}
- return res;
+ if constexpr (!std::is_same<Ret, void>::value)
+ return Ret{};
}
- template <>
- void callMethod<void>(const char *methodName, const char *signature, ...) const
+ template <typename Ret, typename ...Args>
+ Ret callMethod(const char *methodName, Args &&...args) 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();
+ constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
+ if constexpr (std::is_same<Ret, void>::value) {
+ callMethod<void>(methodName, signature.data(), std::forward<Args>(args)...);
+ } else {
+ QtJniTypes::assertPrimitiveType<Ret>();
+ return callMethod<Ret>(methodName, signature.data(), std::forward<Args>(args)...);
}
}
- template <typename T>
- T callMethod(const char *methodName) const
- {
- QtJniTypes::assertPrimitiveType<T>();
- constexpr auto signature = QtJniTypes::methodSignature<T>();
- return callMethod<T>(methodName, signature);
- }
-
- template <typename T>
- QJniObject callObjectMethod(const char *methodName) const
+ template <typename Ret, typename ...Args>
+ QJniObject callObjectMethod(const char *methodName, Args &&...args) const
{
- QtJniTypes::assertObjectType<T>();
- constexpr auto signature = QtJniTypes::methodSignature<T>();
- return callObjectMethod(methodName, signature);
+ QtJniTypes::assertObjectType<Ret>();
+ constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
+ return callObjectMethod(methodName, signature.data(), std::forward<Args>(args)...);
}
QJniObject callObjectMethod(const char *methodName, const char *signature, ...) const;
- template <typename T>
- static T callStaticMethod(const char *className, const char *methodName,
- const char *signature, ...)
- {
- QtJniTypes::assertPrimitiveType<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, ...)
+ template <typename Ret, typename ...Args>
+ static Ret callStaticMethod(const char *className, const char *methodName, const char *signature, Args &&...args)
{
+ QtJniTypes::assertPrimitiveType<Ret>();
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(const char *className, const char *methodName)
- {
- QtJniTypes::assertPrimitiveType<T>();
- constexpr auto signature = QtJniTypes::methodSignature<T>();
- return callStaticMethod<T>(className, methodName, signature);
+ return callStaticMethod<Ret>(clazz, methodName, signature, std::forward<Args>(args)...);
}
- template <typename T>
- static T callStaticMethod(jclass clazz, const char *methodName, const char *signature, ...)
+ template <typename Ret, typename ...Args>
+ static Ret callStaticMethod(jclass clazz, const char *methodName, const char *signature, Args &&...args)
{
- QtJniTypes::assertPrimitiveType<T>();
+ QtJniTypes::assertPrimitiveType<Ret>();
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 callStaticMethod<Ret, Args...>(clazz, id, std::forward<Args>(args)...);
}
- return res;
+ if constexpr (!std::is_same<Ret, void>::value)
+ return Ret{};
}
- template <>
- void callStaticMethod<void>(jclass clazz, const char *methodName,
- const char *signature, ...)
+ template <typename Ret, typename ...Args>
+ static Ret callStaticMethod(jclass clazz, jmethodID methodId, Args &&...args)
{
+ QtJniTypes::assertPrimitiveType<Ret>();
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);
+ if (clazz && methodId) {
+ if constexpr (std::is_same<Ret, void>::value) {
+ callStaticMethodForVoid(env.jniEnv(), clazz, methodId, std::forward<Args>(args)...);
env.checkAndClearExceptions();
+ } else {
+ Ret res{};
+ callStaticMethodForType<Ret>(env.jniEnv(), res, clazz, methodId, std::forward<Args>(args)...);
+ if (env.checkAndClearExceptions())
+ res = {};
+ return res;
}
}
+ if constexpr (!std::is_same<Ret, void>::value)
+ return Ret{};
}
- template <typename T>
- static T callStaticMethod(jclass clazz, jmethodID methodId, ...)
- {
- QtJniTypes::assertPrimitiveType<T>();
- QJniEnvironment env;
- T res{};
- if (clazz && methodId) {
- va_list args;
- va_start(args, methodId);
- callStaticMethodForType<T>(env.jniEnv(), res, clazz, methodId, args);
- va_end(args);
- if (env.checkAndClearExceptions())
- res = {};
- }
- return res;
- }
-
- template <>
- void callStaticMethod<void>(jclass clazz, jmethodID methodId, ...)
+ template <typename Ret, typename ...Args>
+ static Ret callStaticMethod(const char *className, const char *methodName, Args &&...args)
{
+ QtJniTypes::assertPrimitiveType<Ret>();
QJniEnvironment env;
- if (clazz && methodId) {
- va_list args;
- va_start(args, methodId);
- env->CallStaticVoidMethodV(clazz, methodId, args);
- va_end(args);
- env.checkAndClearExceptions();
- }
- }
-
- template <typename T> static T callStaticMethod(jclass clazz, const char *methodName)
- {
- QtJniTypes::assertPrimitiveType<T>();
- constexpr auto signature = QtJniTypes::methodSignature<T>();
- return callStaticMethod<T>(clazz, methodName, signature);
+ jclass clazz = QJniObject::loadClass(className, env.jniEnv());
+ return callStaticMethod<Ret, Args...>(clazz, methodName, std::forward<Args>(args)...);
}
- template <typename T>
- static QJniObject callStaticObjectMethod(const char *className, const char *methodName)
+ template <typename Ret, typename ...Args>
+ static Ret callStaticMethod(jclass clazz, const char *methodName, Args &&...args)
{
- QtJniTypes::assertObjectType<T>();
- constexpr auto signature = QtJniTypes::methodSignature<T>();
- return callStaticObjectMethod(className, methodName, signature);
+ QtJniTypes::assertPrimitiveType<Ret>();
+ constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
+ return callStaticMethod<Ret>(clazz, methodName, signature.data(), std::forward<Args>(args)...);
}
static QJniObject callStaticObjectMethod(const char *className, const char *methodName,
const char *signature, ...);
- template <typename T>
- static QJniObject callStaticObjectMethod(jclass clazz, const char *methodName)
- {
- QtJniTypes::assertObjectType<T>();
- constexpr auto signature = QtJniTypes::methodSignature<T>();
- return callStaticObjectMethod(clazz, methodName, signature);
- }
-
static QJniObject callStaticObjectMethod(jclass clazz, const char *methodName,
const char *signature, ...);
static QJniObject callStaticObjectMethod(jclass clazz, jmethodID methodId, ...);
+
+ template <typename Ret, typename ...Args>
+ static QJniObject callStaticObjectMethod(const char *className, const char *methodName, Args &&...args)
+ {
+ QtJniTypes::assertObjectType<Ret>();
+ constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
+ return callStaticObjectMethod(className, methodName, signature.data(), std::forward<Args>(args)...);
+ }
+
+ template <typename Ret, typename ...Args>
+ static QJniObject callStaticObjectMethod(jclass clazz, const char *methodName, Args &&...args)
+ {
+ QtJniTypes::assertObjectType<Ret>();
+ constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
+ return callStaticObjectMethod(clazz, methodName, signature.data(), std::forward<Args>(args)...);
+ }
+
template <typename T> T getField(const char *fieldName) const
{
QtJniTypes::assertPrimitiveType<T>();
@@ -490,7 +437,7 @@ private:
static jmethodID getMethodID(JNIEnv *env, jclass clazz, const char *name,
const char *signature, bool isStatic = false);
- void callVoidMethodV(JNIEnv *env, jmethodID id, va_list args) const;
+ void callVoidMethodV(JNIEnv *env, jmethodID id, ...) const;
QJniObject callObjectMethodV(const char *methodName, const char *signature,
va_list args) const;
@@ -510,8 +457,11 @@ private:
template<typename T>
static constexpr void callMethodForType(JNIEnv *env, T &res, jobject obj,
- jmethodID id, va_list args)
+ jmethodID id, ...)
{
+ va_list args = {};
+ va_start(args, id);
+
if constexpr(std::is_same<T, jboolean>::value)
res = env->CallBooleanMethodV(obj, id, args);
else if constexpr(std::is_same<T, jbyte>::value)
@@ -530,12 +480,15 @@ private:
res = env->CallDoubleMethodV(obj, id, args);
else
QtJniTypes::staticAssertTypeMismatch();
+ va_end(args);
}
template<typename T>
static constexpr void callStaticMethodForType(JNIEnv *env, T &res, jclass clazz,
- jmethodID id, va_list args)
+ jmethodID id, ...)
{
+ va_list args = {};
+ va_start(args, id);
if constexpr(std::is_same<T, jboolean>::value)
res = env->CallStaticBooleanMethodV(clazz, id, args);
else if constexpr(std::is_same<T, jbyte>::value)
@@ -554,8 +507,18 @@ private:
res = env->CallStaticDoubleMethodV(clazz, id, args);
else
QtJniTypes::staticAssertTypeMismatch();
+ va_end(args);
+ }
+
+ static void callStaticMethodForVoid(JNIEnv *env, jclass clazz, jmethodID id, ...)
+ {
+ va_list args;
+ va_start(args, id);
+ env->CallStaticVoidMethodV(clazz, id, args);
+ va_end(args);
}
+
template<typename T>
static constexpr void getFieldForType(JNIEnv *env, T &res, jobject obj,
jfieldID id)