Класс QJniObject
Удобная оболочка вокруг Java Native Interface (JNI). Подробнее...
| Заголовок: | #include <QJniObject> |
| CMake: | find_package(Qt6 COMPONENTS Core REQUIRED) target_link_libraries(mytarget PRIVATE Qt6::Core) |
| qmake: | QT += core |
| С момента: | Qt 6.1 |
Открытые функции
| QJniObject(jobject object) | |
| QJniObject(jclass clazz, const char *signature, ...) | |
| QJniObject(jclass clazz) | |
| QJniObject(const char *className, const char *signature, ...) | |
| QJniObject(const char *className) | |
| QJniObject() | |
| ~QJniObject() | |
| T | callMethod(const char *methodName, const char *signature, ...) const |
| T | callMethod(const char *methodName) const |
| QJniObject | callObjectMethod(const char *methodName) const |
| QJniObject | callObjectMethod(const char *methodName, const char *signature, ...) const |
| QByteArray | className() const |
| T | getField(const char *fieldName) const |
| QJniObject | getObjectField(const char *fieldName) const |
| QJniObject | getObjectField(const char *fieldName, const char *signature) const |
| bool | isValid() const |
| jobject | object() const |
| jclass | objectClass() const |
| void | setField(const char *fieldName, T value) |
| void | setField(const char *fieldName, const char *signature, T value) |
| QString | toString() const |
| QJniObject & | operator=(T object) |
Статические открытые члены
| T | callStaticMethod(const char *className, const char *methodName, const char *signature, ...) |
| T | callStaticMethod(const char *className, const char *methodName) |
| T | callStaticMethod(jclass clazz, const char *methodName, const char *signature, ...) |
| T | callStaticMethod(jclass clazz, jmethodID methodId, ...) |
| T | callStaticMethod(jclass clazz, const char *methodName) |
| QJniObject | callStaticObjectMethod(const char *className, const char *methodName) |
| QJniObject | callStaticObjectMethod(const char *className, const char *methodName, const char *signature, ...) |
| QJniObject | callStaticObjectMethod(jclass clazz, const char *methodName) |
| QJniObject | callStaticObjectMethod(jclass clazz, const char *methodName, const char *signature, ...) |
| QJniObject | callStaticObjectMethod(jclass clazz, jmethodID methodId, ...) |
| QJniObject | fromLocalRef(jobject localRef) |
| QJniObject | fromString(const QString &string) |
| T | getStaticField(const char *className, const char *fieldName) |
| T | getStaticField(jclass clazz, const char *fieldName) |
| QJniObject | getStaticObjectField(const char *className, const char *fieldName) |
| QJniObject | getStaticObjectField(const char *className, const char *fieldName, const char *signature) |
| QJniObject | getStaticObjectField(jclass clazz, const char *fieldName) |
| QJniObject | getStaticObjectField(jclass clazz, const char *fieldName, const char *signature) |
| bool | isClassAvailable(const char *className) |
| void | setStaticField(const char *className, const char *fieldName, T value) |
| void | setStaticField(const char *className, const char *fieldName, const char *signature, T value) |
| void | setStaticField(jclass clazz, const char *fieldName, const char *signature, T value) |
| void | setStaticField(jclass clazz, const char *fieldName, T value) |
Связанные нечлены
| bool | operator!=(const QJniObject &o1, const QJniObject &o2) |
| bool | operator==(const QJniObject &o1, const QJniObject &o2) |
Подробное описание
Класс QJniObject оборачивает ссылку на объект Java, гарантируя, что он не будет собран сборщиком мусора, и предоставляя доступ к большинству вызовов методов JNIEnv (член, статический) и полям (сеттер, геттер). Он устраняет большое количество служебного кода, который обычно необходим при прямом доступе к JNI для каждой операции, включая обработку исключений.
Примечание: Этот API был разработан и протестирован для использования с Android. Он не был протестирован для других платформ.
Общие замечания
- Имена классов должны быть полностью квалифицированными, например:
"java/lang/String". - Подписи методов написаны как
"(ArgumentsTypes)ReturnType", см. Типы JNI. - Все типы объектов возвращаются как QJniObject.
Подписи методов
Для функций без аргументов QJniObject предоставляет удобные функции, которые будут использовать правильную подпись на основе предоставленного шаблона типа. Например:
jint x = QJniObject::callMethod<jint>("getSize");
QJniObject::callMethod<void>("touch"); В других случаях вам необходимо указать подпись самостоятельно, и важно, чтобы подпись соответствовала вызываемой функции. Структура подписи "(ArgumentsTypes)ReturnType". Типы массивов в подписи должны иметь префикс [, а имена типов с полным квалификатором Object должны иметь префикс L и суффикс ;.
Следующий пример демонстрирует, как вызвать две разные статические функции:
// Java class
package org.qtproject.qt;
class TestClass
{
static String fromNumber(int x) { ... }
static String[] stringArray(String s1, String s2) { ... }
} Подпись для первой функции "(I)Ljava/lang/String;":
// C++ code
QJniObject stringNumber = QJniObject::callStaticObjectMethod("org/qtproject/qt/TestClass",
"fromNumber"
"(I)Ljava/lang/String;",
10); и подпись для второй функции "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;":
// C++ code
QJniObject string1 = QJniObject::fromString("String1");
QJniObject string2 = QJniObject::fromString("String2");
QJniObject stringArray = QJniObject::callStaticObjectMethod("org/qtproject/qt/TestClass",
"stringArray"
"(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"
string1.object<jstring>(),
string2.object<jstring>()); Обработка исключений Java
После вызова функций Java, которые могут генерировать исключения, важно проверить, обработать и очистить любое исключение перед продолжением. Все функции QJniObject обрабатывают исключения внутри, сообщая и очищая их, что избавляет код клиента от необходимости обработки исключений.
Примечание: Пользователь должен вручную обрабатывать исключения при прямом использовании вызовов JNI JNIEnv. Небезопасно выполнять другие вызовы JNI, когда исключения ожидаются. Более подробная информация см. в QJniEnvironment::checkAndClearExceptions().
Методы Java Native
Методы Java Native позволяют вызывать нативный код из Java. Это делается путем создания объявления функции в Java и добавления к ней префикса native. Прежде чем нативная функция сможет быть вызвана из Java, вам необходимо сопоставить нативную функцию Java с нативной функцией в вашем коде. Сопоставление функций может быть выполнено с помощью вызова QJniEnvironment::registerNativeMethods().
Следующий пример демонстрирует, как это можно сделать.
Реализация на Java:
class FooJavaClass
{
public static void foo(int x)
{
if (x < 100)
callNativeOne(x);
else
callNativeTwo(x);
}
private static native void callNativeOne(int x);
private static native void callNativeTwo(int x);
} Реализация на C++:
static void fromJavaOne(JNIEnv *env, jobject thiz, jint x)
{
Q_UNUSED(env);
Q_UNUSED(thiz);
qDebug() << x << "< 100";
}
static void fromJavaTwo(JNIEnv *env, jobject thiz, jint x)
{
Q_UNUSED(env);
Q_UNUSED(thiz);
qDebug() << x << ">= 100";
}
void foo()
{
// register the native methods first, ideally it better be done with the app start
const JNINativeMethod methods[] =
{{"callNativeOne", "(I)V", reinterpret_cast<void *>(fromJavaOne)},
{"callNativeTwo", "(I)V", reinterpret_cast<void *>(fromJavaTwo)}};
QJniEnvironment env;
env.registerNativeMethods("my/java/project/FooJavaClass", methods, 2);
// Call the java method which will calls back to the C++ functions
QJniObject::callStaticMethod<void>("my/java/project/FooJavaClass", "foo", "(I)V", 10); // Output: 10 < 100
QJniObject::callStaticMethod<void>("my/java/project/FooJavaClass", "foo", "(I)V", 100); // Output: 100 >= 100
} Жизненный цикл объекта Java
Большинство объектов, полученных из Java, будут локальными ссылками и останутся действительными до возвращения из нативного метода. После этого объект становится доступным для сборки мусора. Если ваш код создает много локальных ссылок в цикле, вы должны удалять их вручную с каждой итерацией, иначе у вас может закончится память. Более подробную информацию см. в Обзор проектирования JNI: глобальные и локальные ссылки. Локальные ссылки, созданные вне области нативного метода, должны быть удалены вручную, так как сборщик мусора не освободит их автоматически, поскольку мы используем AttachCurrentThread. Более подробную информацию см. в Советы по JNI: локальные и глобальные ссылки.
Если вы хотите сохранить объект Java живым, вам необходимо либо создать новую глобальную ссылку на объект и освободить ее, когда вы закончите, либо создать новый QJniObject и позволить ему управлять жизненным циклом объекта Java.
Примечание: QJniObject управляет только своими собственными ссылками. Если вы создаете QJniObject из глобальной или локальной ссылки, эта ссылка не будет освобождена QJniObject.
Типы JNI
Типы объектов
| Тип | Подпись |
|---|---|
| jobject | Ljava/lang/Object; |
| jclass | Ljava/lang/Class; |
| jstring | Ljava/lang/String; |
| jthrowable | Ljava/lang/Throwable; |
| jobjectArray | [Ljava/lang/Object; |
| jarray | [<type> |
| jbooleanArray | [Z |
| jbyteArray | [B |
| jcharArray | [C |
| jshortArray | [S |
| jintArray | [I |
| jlongArray | [J |
| jfloatArray | [F |
| jdoubleArray | [D |
Примитивные типы
| Тип | Подпись |
|---|---|
| jboolean | Z |
| jbyte | B |
| jchar | C |
| jshort | S |
| jint | I |
| jlong | J |
| jfloat | F |
| jdouble | D |
Другие
| Тип | Подпись |
|---|---|
| void | V |
| Пользовательский тип | L<полное_имя>; |
Дополнительную информацию о JNI см. в Спецификации Java Native Interface.
См. также QJniEnvironment и object().
Документация по членам функций
QJniObject::QJniObject(jobject object)
Создает новый объект JNI вокруг объекта Java object.
Примечание: QJniObject будет содержать ссылку на объект Java object и освободит ее при уничтожении. Любые ссылки на объект Java object вне QJniObject должны управляться вызывающим объектом. В большинстве случаев вы не должны вызывать эту функцию с локальной ссылкой, если не планируете самостоятельно управлять локальной ссылкой. См. QJniObject::fromLocalRef() для преобразования локальной ссылки в QJniObject.
См. также fromLocalRef().
QJniObject::QJniObject(jclass clazz, const char *signature, ...)
Создает новый объект JNI из clazz, вызывая конструктор с signature, определяющим типы последующих аргументов.
QJniEnvironment env;
jclass myClazz = env.findClass("org/qtproject/qt/TestClass");
QJniObject(myClazz, "(I)V", 3); QJniObject::QJniObject(jclass clazz)
Создает новый объект JNI, вызывая конструктор по умолчанию для clazz.
Примечание: QJniObject создаст новую ссылку на класс clazz и освободит ее при уничтожении. Ссылки на созданный вне QJniObject класс должны управляться вызывающим объектом.
QJniObject::QJniObject(const char *className, const char *signature, ...)
Создает новый объект JNI, вызывая конструктор className с signature, определяющим типы последующих аргументов.
QJniEnvironment env;
char* str = "Hello";
jstring myJStringArg = env->NewStringUTF(str);
QJniObject myNewJavaString("java/lang/String", "(Ljava/lang/String;)V", myJStringArg); QJniObject::QJniObject(const char *className)
Создает новый объект JNI, вызывая конструктор по умолчанию для className.
QJniObject myJavaString("java/lang/String"); QJniObject::QJniObject()
Создает недействительный объект JNI.
См. также isValid().
QJniObject::~QJniObject()
Уничтожает объект JNI и освобождает все ссылки, удерживаемые объектом JNI.
template <typename T> T QJniObject::callMethod(const char *methodName, const char *signature, ...) const
Вызывает метод объекта methodName с signature, определяющим типы последующих аргументов.
QJniObject myJavaStrin("org/qtproject/qt/TestClass");
jint index = myJavaString.callMethod<jint>("indexOf", "(I)I", 0x0051); template <typename T> T QJniObject::callMethod(const char *methodName) const
Вызывает метод methodName и возвращает значение.
QJniObject myJavaStrin("org/qtproject/qt/TestClass");
jint size = myJavaString.callMethod<jint>("length"); template <typename T> QJniObject QJniObject::callObjectMethod(const char *methodName) const
Вызывает метод объекта Java methodName и возвращает новый QJniObject для возвращаемого объекта Java.
QJniObject myJavaString = QJniObject::fromString("Hello, Java");
QJniObject myJavaString2 = myJavaString1.callObjectMethod<jstring>("toString"); QJniObject QJniObject::callObjectMethod(const char *methodName, const char *signature, ...) const
Вызывает метод объекта Java methodName с signature, определяющим типы последующих аргументов.
QJniObject myJavaString = QJniObject::fromString("Hello, Java");
QJniObject mySubstring = myJavaString.callObjectMethod("substring",
"(II)Ljava/lang/String;", 7, 11);
[static] template <typename T> T QJniObject::callStaticMethod(const char *className, const char *methodName, const char *signature, ...)
Вызывает статический метод methodName из класса className с signature, определяющим типы последующих аргументов.
jint a = 2;
jint b = 4;
jint max = QJniObject::callStaticMethod<jint>("java/lang/Math", "max", "(II)I", a, b);
[static] template <typename T> T QJniObject::callStaticMethod(const char *className, const char *methodName)
Вызывает статический метод methodName класса className и возвращает значение.
jint value = QJniObject::callStaticMethod<jint>("MyClass", "staticMethod");
[static] template <typename T> T QJniObject::callStaticMethod(jclass clazz, const char *methodName, const char *signature, ...)
Вызывает статический метод methodName из clazz с signature, определяющим типы последующих аргументов.
QJniEnvironment env;
jclass javaMathClass = env.findClass("java/lang/Math");
jint a = 2;
jint b = 4;
jint max = QJniObject::callStaticMethod<jint>(javaMathClass, "max", "(II)I", a, b);
[static] template <typename T> T QJniObject::callStaticMethod(jclass clazz, jmethodID methodId, ...)
Вызывает статический метод, идентифицируемый methodId, из класса clazz с последующими аргументами. Полезно, когда clazz и methodId уже кэшированы из предыдущих операций.
QJniEnvironment env;
jclass javaMathClass = env.findClass("java/lang/Math");
jmethodID methodId = env.findStaticMethod(javaMathClass, "max", "(II)I");
if (methodId != 0) {
jint a = 2;
jint b = 4;
jint max = QJniObject::callStaticMethod<jint>(javaMathClass, methodId, a, b);
}
[static] template <typename T> T QJniObject::callStaticMethod(jclass clazz, const char *methodName)
Вызывает статический метод methodName в clazz и возвращает значение.
QJniEnvironment env;
jclass javaMathClass = env.findClass("java/lang/Math");
jdouble randNr = QJniObject::callStaticMethod<jdouble>(javaMathClass, "random");
[static] template <typename T> QJniObject QJniObject::callStaticObjectMethod(const char *className, const char *methodName)
Вызывает статический метод с methodName в классе className.
QJniObject string = QJniObject::callStaticObjectMethod<jstring>("CustomClass", "getClassName");
[static] QJniObject QJniObject::callStaticObjectMethod(const char *className, const char *methodName, const char *signature, ...)
Вызывает статический метод methodName из класса className с signature, определяющим типы последующих аргументов.
QJniObject thread = QJniObject::callStaticObjectMethod("java/lang/Thread", "currentThread",
"()Ljava/lang/Thread;");
QJniObject string = QJniObject::callStaticObjectMethod("java/lang/String", "valueOf",
"(I)Ljava/lang/String;", 10);
[static] template <typename T> QJniObject QJniObject::callStaticObjectMethod(jclass clazz, const char *methodName)
Вызывает статический метод с methodName в clazz.
[static] QJniObject QJniObject::callStaticObjectMethod(jclass clazz, const char *methodName, const char *signature, ...)
Вызывает статический метод methodName из класса clazz с signature, определяющим типы последующих аргументов.
[static] QJniObject QJniObject::callStaticObjectMethod(jclass clazz, jmethodID methodId, ...)
Вызывает статический метод, идентифицируемый methodId, из класса clazz с последующими аргументами. Полезно, когда clazz и methodId уже кэшированы из предыдущих операций.
QJniEnvironment env;
jclass clazz = env.findClass("java/lang/String");
jmethodID methodId = env.findStaticMethod(clazz, "valueOf", "(I)Ljava/lang/String;");
if (methodId != 0)
QJniObject str = QJniObject::callStaticObjectMethod(clazz, methodId, 10);
[since 6.2] QByteArray QJniObject::className() const
Возвращает имя объекта класса, удерживаемого QJniObject, как %%%CODE_BLOCK_44%%.
Эта функция была добавлена в Qt 6.2.
[static] QJniObject QJniObject::fromLocalRef(jobject localRef)
Создает QJniObject из локальной JNI-ссылок localRef. Эта функция принимает на себя владение localRef и освобождает его перед возвратом.
Примечание: Используйте эту функцию только с локальной JNI-ссылкой. Например, большинство прямых вызовов JNI через среду JNI возвращают локальные ссылки на объект Java.
jobject localRef = env->GetObjectArrayElement(array, index); QJniObject element = QJniObject::fromLocalRef(localRef);
[static] QJniObject QJniObject::fromString(const QString &string)
Создает строку Java из QString string и возвращает QJniObject, содержащий эту строку.
QString myQString = "QString"; QJniObject myJavaString = QJniObject::fromString(myQString);
См. также toString().
template <typename T> T QJniObject::getField(const char *fieldName) const
Извлекает значение поля fieldName.
QJniObject volumeControl("org/qtproject/qt/TestClass");
jint fieldValue = volumeControl.getField<jint>("FIELD_NAME"); template <typename T> QJniObject QJniObject::getObjectField(const char *fieldName) const
Извлекает объект JNI из поля fieldName.
QJniObject field = jniObject.getObjectField<jstring>("FIELD_NAME"); QJniObject QJniObject::getObjectField(const char *fieldName, const char *signature) const
Извлекает объект JNI из поля fieldName с signature.
Примечание: Эта функция может использоваться без шаблона типа.
QJniObject field = jniObject.getObjectField("FIELD_NAME", "Ljava/lang/String;");
[static] template <typename T> T QJniObject::getStaticField(const char *className, const char *fieldName)
Извлекает значение из статического поля fieldName класса className.
[static] template <typename T> T QJniObject::getStaticField(jclass clazz, const char *fieldName)
Извлекает значение из статического поля fieldName в clazz.
[static] template <typename T> QJniObject QJniObject::getStaticObjectField(const char *className, const char *fieldName)
Извлекает объект из поля fieldName в классе className.
QJniObject jobj = QJniObject::getStaticObjectField<jstring>("class/with/Fields", "FIELD_NAME");
[static] QJniObject QJniObject::getStaticObjectField(const char *className, const char *fieldName, const char *signature)
Извлекает объект JNI из поля fieldName с signature из класса className.
Примечание: Эта функция может использоваться без шаблона типа.
QJniObject jobj = QJniObject::getStaticObjectField("class/with/Fields", "FIELD_NAME",
"Ljava/lang/String;");
[static] template <typename T> QJniObject QJniObject::getStaticObjectField(jclass clazz, const char *fieldName)
Извлекает объект из поля fieldName в clazz.
QJniObject jobj = QJniObject::getStaticObjectField<jstring>(clazz, "FIELD_NAME");
[static] QJniObject QJniObject::getStaticObjectField(jclass clazz, const char *fieldName, const char *signature)
Извлекает объект JNI из поля fieldName с signature из класса clazz.
Примечание: Эта функция может использоваться без шаблона типа.
QJniObject jobj = QJniObject::getStaticObjectField(clazz, "FIELD_NAME", "Ljava/lang/String;");
[static] bool QJniObject::isClassAvailable(const char *className)
Возвращает true, если класс Java className доступен.
if (QJniObject::isClassAvailable("java/lang/String")) {
// condition statement
} bool QJniObject::isValid() const
Возвращает true, если этот экземпляр содержит действительный объект Java.
QJniObject qjniObject; // ==> isValid() == false
QJniObject qjniObject(0) // ==> isValid() == false
QJniObject qjniObject("could/not/find/Class") // ==> isValid() == false jobject QJniObject::object() const
Возвращает объект, удерживаемый QJniObject, либо как jobject, либо как тип T. T может быть одним из типов объектов JNI.
QJniObject string = QJniObject::fromString("Hello, JNI");
jstring jstring = string.object<jstring>(); Примечание: Возвращаемый объект все еще поддерживается этим QJniObject. Чтобы сохранить объект дольше срока действия этого QJniObject, например, чтобы записать его для последующего использования, самый простой способ — сохранить его в другом QJniObject с соответствующим сроком действия. В качестве альтернативы, можно создать новую глобальную ссылку на объект и сохранить его, позаботившись об освобождении, когда он больше не нужен.
void functionScope()
{
QString helloString("Hello");
jstring myJString = 0;
{
QJniObject string = QJniObject::fromString(helloString);
myJString = string.object<jstring>();
}
// Ops! myJString is no longer valid.
}
[since 6.2] jclass QJniObject::objectClass() const
Возвращает объект класса, удерживаемый QJniObject, как jclass.
Примечание: Возвращаемый объект все еще поддерживается этим QJniObject. Чтобы сохранить объект дольше срока действия этого QJniObject, например, чтобы записать его для последующего использования, самый простой способ — сохранить его в другом QJniObject с соответствующим сроком действия. В качестве альтернативы, можно создать новую глобальную ссылку на объект и сохранить его, позаботившись об освобождении, когда он больше не нужен.
Эта функция была добавлена в Qt 6.2.
template <typename T> void QJniObject::setField(const char *fieldName, T value)
Устанавливает значение fieldName на value.
QJniObject obj;
obj.setField<jint>("AN_INT_FIELD", 10);
jstring myString = ...;
obj.setField<jstring>("A_STRING_FIELD", myString); template <typename T> void QJniObject::setField(const char *fieldName, const char *signature, T value)
Устанавливает значение fieldName со signature на value.
QJniObject stringArray = ...;
QJniObject obj = ...;
obj.setObjectField<jobjectArray>("KEY_VALUES", "([Ljava/lang/String;)V",
stringArray.object<jobjectArray>())
[static] template <typename T> void QJniObject::setStaticField(const char *className, const char *fieldName, T value)
Устанавливает статическое поле fieldName класса className на value.
[static] template <typename T> void QJniObject::setStaticField(const char *className, const char *fieldName, const char *signature, T value)
Устанавливает статическое поле fieldName класса className на value, используя установщик с signature.
[static] template <typename T> void QJniObject::setStaticField(jclass clazz, const char *fieldName, const char *signature, T value)
Устанавливает статическое поле fieldName класса clazz на value, используя установщик с signature.
[static] template <typename T> void QJniObject::setStaticField(jclass clazz, const char *fieldName, T value)
Устанавливает статическое поле fieldName класса clazz на value.
QString QJniObject::toString() const
Возвращает QString со строковым представлением объекта Java. Вызов этой функции для объекта Java String — удобный способ получить фактические данные строки.
QJniObject string = ...; // "Hello Java" QString qstring = string.toString(); // "Hello Java"
См. также fromString().
template <typename T> QJniObject &QJniObject::operator=(T object)
Заменяет текущий объект на object. Старый объект Java будет освобождён.
Связанные нечленные функции
bool operator!=(const QJniObject &o1, const QJniObject &o2)
Возвращает true, если o1 ссылается на другой объект, чем o2.
bool operator==(const QJniObject &o1, const QJniObject &o2)
Возвращает true, если оба объекта, o1 и o2, ссылаются на один и тот же объект Java или оба являются NULL. В противном случае возвращает false.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.2/qjniobject.html