Uso de JNI para la comunicación entre JAVA y C++ (introducción al ejemplo de Qt JNI Messenger) - Desarrollo de Android, Qt

Prefacio

Usar Qt para desarrollar Android requiere inevitablemente llamar al código subyacente, es decir, llamar a la función Java, que usa JNI.

Puntos de conocimiento básico de JNI

Palabras clave nativas

La palabra clave nativa indica que el método modificado es un método nativo. La implementación correspondiente del método no está en el archivo actual (es decir, solo se declara aquí), sino en archivos implementados en otros lenguajes (como C y C++) . El lenguaje Java en sí no puede acceder ni operar el sistema operativo subyacente, pero puede llamar a otros lenguajes a través de la interfaz JNI para lograr el acceso a la capa subyacente.

proyecto de trabajo, jclass

Puedes adivinarlo mirando el nombre: jclass es la clase en sí, jobject es la instancia de la clase,

En general:

  • Cuando el método nativo definido en Java es un método estático, el segundo parámetro es jclass, y jclass representa la clase misma de la clase a la que pertenece el método nativo.
  •  Cuando el método nativo definido en Java es un método no estático, el segundo parámetro es jobject, y jobject representa el objeto de instancia de la clase a la que pertenece el método nativo.

Consulte el siguiente artículo para obtener más detalles:

Guía de introducción a JNI/NDK: jobject y jclass_jni jobject_IT Blog de Xiansen-Blog de CSDN

 JNIEnv

JNIEnv es el entorno básico que proporciona funciones nativas de JNI. Está relacionado con subprocesos. JNIEnv de diferentes subprocesos son independientes entre sí. JNIEnv es un puntero de interfaz JNI que apunta a una tabla de funciones de métodos nativos . Cada miembro de la tabla de funciones apunta a una función JNI. , los métodos nativos acceden a estructuras de datos en la JVM a través de funciones JNI.

Consulte el siguiente artículo para obtener más detalles:

Guía de introducción a JNI/NDK: JavaVM y JNIEnv_javavm jni_IT Blog de Xiansen-Blog de CSDN

Método JNINativo

JNINativeMethod Esta estructura se utiliza para describir la información del método nativo JNI que debe registrarse. Páselo en la tabla de funciones de registro JNIEnv::RegisterNatives.

    jint RegisterNatives(jclass clazz, const JNINativeMethod* methods,
        jint nMethods)

Lea el siguiente artículo para aprender cómo usarlo:

JNINativeMethod de JNI - Android_Diez años menos Blog-CSDN Blog

usar

perfil

QT += androidextras

java llama a C++

Definir métodos nativos en código java.

package org.qtproject.example.jnimessenger;

public class JniMessenger
{
    //用 native 声明的方法表示告知 JVM 调用,该方法在外部定义,一个native Method就是一个 Java 调用非 Java 代码的接口。
    private static native void callFromJava(String message);

    public JniMessenger() {}

    public static void printFromJava(String message)
    {
        System.out.println("This is printed from JAVA, message is: " + message);

       //这里调用了native方法(外部实现的)
        callFromJava("Hello from JAVA!");
    }
}

Implementado en c++: aquí se llama a la instancia de JniMessenger de c++ para emitir la señal messageFromJava, y la señal se pasa como valor de parámetro. Todas las implementaciones definidas en C++ están en este formato.

 estático 【return】 funcName (JNIEnv *env, jclass, 【arg1,arg2 ...】)

【return】 funcName (JNIEnv *env, jobject,【arg1,arg2...】)

JniMessenger *JniMessenger::m_instance = nullptr;

static void callFromJava(JNIEnv *env, jclass /*thiz*/, jstring value)

{
    emit JniMessenger::instance()->messageFromJava(env->GetStringUTFChars(value, nullptr));
}

 Convertir jstring a char* 

const char* GetStringUTFChars(cadena jstring, jboolean* isCopy) 

 Lo anterior es un callFromJava implementado en C ++, pero si desea asociarlo con Java, también debe registrar este puntero de función en JNIEnv. Como se mencionó en el conocimiento básico anterior, "JNIEnv es un puntero de interfaz JNI que apunta a una función de un método local ".Table ", lo que debemos hacer es registrar esta función en esta tabla de funciones

JniMessenger::JniMessenger(QObject *parent) : QObject(parent)
{
    m_instance = this;

   //c++ 本地定义的 jni native方法
    JNINativeMethod methods[] {
   
   {"callFromJava", "(Ljava/lang/String;)V", reinterpret_cast<void *>(callFromJava)}};

    QAndroidJniObject javaClass("org/qtproject/example/jnimessenger/JniMessenger");

   //注册
    QAndroidJniEnvironment env;
    jclass objectClass = env->GetObjectClass(javaClass.object<jobject>());
    env->RegisterNatives(objectClass,
                         methods,
                         sizeof(methods) / sizeof(methods[0]));
    //释放内存
    env->DeleteLocalRef(objectClass);
}

 

C++ llama a java

Es relativamente sencillo llamar a funciones de Java en C++, de la siguiente manera

Ejemplo de función estática:

void JniMessenger::printFromJava(const QString &message)
{
    QAndroidJniObject javaMessage = QAndroidJniObject::fromString(message);
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/example/jnimessenger/JniMessenger", //类名
                                       "printFromJava",//函数名
                                       "(Ljava/lang/String;)V",//(参数类型)返回类型
                                        javaMessage.object<jstring>());//传入参数
}

Ejemplo de función ordinaria (si printFromJava definido en Java es una función ordinaria):

void JniMessenger::printFromJava(const QString &message)
{
    QAndroidJniObject javaMessage = QAndroidJniObject::fromString(message);

    QAndroidJniObject javaClass("org/qtproject/example/jnimessenger/JniMessenger");
    javaClass.callObjectMethod("printFromJava",
                               "(Ljava/lang/String;)V",
                                javaMessage.object<jstring>());
}

 

Conclusión

Esto es solo el comienzo. Si quieres jugar con Android, aún debes aprender o comprender todo el marco.

Supongo que te gusta

Origin blog.csdn.net/xiaopei_yan/article/details/130884889
Recomendado
Clasificación