Utiliser JNI pour la communication entre JAVA et C++ (introduction de l'exemple Qt JNI Messenger) - Développement Android, Qt

Préface

Utiliser Qt pour développer Android nécessite inévitablement d'appeler le code sous-jacent, c'est-à-dire d'appeler la fonction Java, qui utilise JNI.

Points de connaissances de base de JNI

Mots-clés natifs

Le mot-clé natif indique que la méthode modifiée est une méthode native. L'implémentation correspondante de la méthode ne se trouve pas dans le fichier actuel (c'est-à-dire qu'elle est uniquement déclarée ici), mais dans des fichiers implémentés dans d'autres langages (tels que C et C++) . Le langage Java lui-même ne peut pas accéder au système d'exploitation sous-jacent et le faire fonctionner, mais il peut appeler d'autres langages via l'interface JNI pour accéder à la couche sous-jacente.

jobject、jclass

Vous pouvez le deviner en regardant le nom : jclass est la classe elle-même, jobject est l'instance de classe,

En général:

  • Lorsque la méthode native définie en Java est une méthode statique, le deuxième paramètre est jclass, et jclass représente la classe elle-même de la classe à laquelle appartient la méthode native.
  •  Lorsque la méthode native définie en Java est une méthode non statique, le deuxième paramètre est jobject, et jobject représente l'objet instance de la classe à laquelle appartient la méthode native.

Veuillez consulter l'article suivant pour plus de détails :

Guide de démarrage JNI/NDK - jobject et jclass_jni jobject_IT Xiansen's Blog-CSDN Blog

 JNIEnv

JNIEnv est l'environnement de base qui fournit les fonctions natives JNI. Il est lié aux threads. JNIEnv des différents threads est indépendant les uns des autres. JNIEnv est un pointeur d'interface JNI qui pointe vers une table de fonctions de méthodes natives . Chaque membre de la table de fonctions pointe à une fonction JNI. , les méthodes natives accèdent aux structures de données dans la JVM via les fonctions JNI.

Veuillez consulter l'article suivant pour plus de détails :

Guide de démarrage JNI/NDK : JavaVM et JNIEnv_javavm jni_IT Xiansen's Blog-CSDN Blog

Méthode JNINative

JNINativeMethod Cette structure est utilisée pour décrire les informations sur la méthode native JNI qui doivent être enregistrées. Passez-le dans la table des fonctions d'enregistrement JNIEnv::RegisterNatives.

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

Veuillez lire l'article suivant pour savoir comment l'utiliser :

JNINativeMethod de JNI - Android_Ten Years Less Blog-CSDN Blog

utiliser

profil

QT += androidextras

Java appelle C++

Définir des méthodes natives dans le code 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!");
    }
}

Implémenté en c++ : ici, l'instance c++ JniMessenger est appelée pour émettre le signal messageFromJava, et le signal est transmis en tant que valeur de paramètre. Les implémentations définies en C++ sont toutes dans ce format

 static 【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 en char* 

const char* GetStringUTFChars(chaîne jstring, jboolean* isCopy) 

 Ce qui précède est un callFromJava implémenté en C++, mais si vous souhaitez l'associer à Java, vous devez également enregistrer ce pointeur de fonction dans JNIEnv. Comme mentionné dans les connaissances de base ci-dessus, "JNIEnv est un pointeur d'interface JNI qui pointe vers une fonction d'une méthode locale.Table " , ce que nous devons faire est d'enregistrer cette fonction dans cette table de fonctions

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++ appelle Java

Il est relativement simple d'appeler des fonctions Java en C++, comme suit

Exemple de fonction statique :

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>());//传入参数
}

Exemple de fonction ordinaire (si printFromJava défini en java est une fonction ordinaire) :

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>());
}

 

Conclusion

Ce n'est que le début. Si vous souhaitez jouer avec Android, vous devez encore apprendre ou comprendre l'intégralité du framework.

Je suppose que tu aimes

Origine blog.csdn.net/xiaopei_yan/article/details/130884889
conseillé
Classement