[Android JNI] --- Static registration and dynamic registration realize java and native call each other

1 The method of static registration realizes the mutual calling of c/c++ and java

Access Java methods in C/C++
Access methods of Java parent classes in
C/C++ Access/modify Java variables in C/C++

Access C/C++ methods in Java
Access/modify C/C++ variables in Java

The implementation code is given as follows:
// StaticReg.java

package com.android.javacpp;

import android.util.Log;

public class StaticReg {
    
    
    private String  TAG = "JC_StaticReg";

    private String TestString = "1234";
    private int TestInt = 1234;

    // java access c++
    public native String geJNIString();
    public native int getJNIInt(Object obj);
    public native void passStringToJNI(String str);

    // 用于调用 C++ 方法
    public native int callJNIAdd(int a, int b);

    // c++ access java
    public native void setJavaString();
    public native void setJavaInt();

    public native int callJavaMethodAdd();

    public int Add(int a, int b) {
    
    
        return a + b;
    }

    public void StaticRegTest()
    {
    
    
        Log.d(TAG, "geJNIString: " + geJNIString());
        Log.d(TAG, "getJNIInt: " + getJNIInt(this));
        passStringToJNI("12345678");
        int result = callJNIAdd(999, 999);
        Log.d(TAG, "callNativeAdd: " +  result);

        // c++ access java
        Log.d(TAG, "before modif TestString: " + TestString);
        setJavaString();
        Log.d(TAG, "after modif TestString: " + TestString);

        Log.d(TAG, "before modif TestInt: " + TestInt);
        setJavaInt();
        Log.d(TAG, "after modif TestInt: " + TestInt);

        int result2 = callJavaMethodAdd();
        Log.d(TAG, "callJavaMethodAdd: " +  result2);
    }
}

StaticReg.cpp

#include <jni.h>
#include <string>
#include "log.h"
#include "DynamicReg.h"

extern "C"
JNIEXPORT jstring JNICALL
Java_com_android_javacpp_StaticReg_geJNIString(JNIEnv *env, jobject thiz) {
    
    
    // TODO: implement geJNIString()
    return env->NewStringUTF("the string from C++");
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_android_javacpp_StaticReg_getJNIInt(JNIEnv *env, jobject thiz, jobject obj) {
    
    
    // TODO: implement getJNIInt()
    jint inttest = 999;
    return inttest;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_android_javacpp_StaticReg_passStringToJNI(JNIEnv *env, jobject thiz, jstring str) {
    
    
    // TODO: implement passStringToJNI()
    const char* utfChars = env->GetStringUTFChars(str, nullptr);
    std::string strtest = utfChars;
    LOGD("string from java: %s", strtest.c_str());
    env->ReleaseStringUTFChars(str, utfChars);
}
extern "C"
JNIEXPORT jint JNICALL
Java_com_android_javacpp_StaticReg_callJNIAdd(JNIEnv *env, jobject thiz, jint a, jint b) {
    
    
    // TODO: implement callJNIAdd()
    return a + b;
}

extern "C"
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    
    
    JNIEnv *env = NULL;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
    
    
        return JNI_ERR;
    }
    jint result = DynamicReg::GetInstance().RegisterNatives(env);
    LOGD("RegisterNatives result: %d", result);
    return JNI_VERSION_1_6;
}

// c++ access java method/var
extern "C"
JNIEXPORT void JNICALL
Java_com_android_javacpp_StaticReg_setJavaString(JNIEnv *env, jobject thiz) {
    
    
    // TODO: implement setJavaString()
    jclass activityClass=env->GetObjectClass(thiz);
//    获取java层的text属性
    jfieldID idText = env->GetFieldID(activityClass, "TestString", "Ljava/lang/String;");
    //给text属性赋值
    jstring text1 = env->NewStringUTF("5678");
    env->SetObjectField(thiz, idText, text1);

//    通过jobject参数获取MainActivity对应的class对象在Native层的映射jclass 对象
//    通过jclass 对象得到text属性的id
//    通过text属性id去修改text的值
}


extern "C"
JNIEXPORT void JNICALL
Java_com_android_javacpp_StaticReg_setJavaInt(JNIEnv *env, jobject thiz) {
    
    
    // TODO: implement setJavaInt()
    jclass activityClass=env->GetObjectClass(thiz);
    //  获取java层的text属性
    jfieldID idText = env->GetFieldID(activityClass, "TestInt", "I");
    //给text属性赋值
    jint text1 = 5678;
    env->SetIntField(thiz, idText, text1);
}


extern "C"
JNIEXPORT jint JNICALL
Java_com_android_javacpp_StaticReg_callJavaMethodAdd(JNIEnv *env, jobject thiz) {
    
    
    // TODO: implement callJavaMethodAdd()
    // 获取 MainActivity 类的引用
    jclass clazz = env->FindClass("com/android/javacpp/StaticReg");
    if (clazz == nullptr) {
    
    
        return -1;
    }

    // 获取 MainActivity 实例的引用
    jobject activityObj = env->NewObject(clazz, env->GetMethodID(clazz, "<init>", "()V"));
    if (activityObj == nullptr) {
    
    
        return -1;
    }

    // 调用 MainActivity 中的 add 方法
    jmethodID addMethodId = env->GetMethodID(clazz, "Add", "(II)I");
    if (addMethodId == nullptr) {
    
    
        return -1;
    }
    return env->CallIntMethod(activityObj, addMethodId, 100, 20);
}

2 The way of dynamic registration realizes the method/variable of c/c++ calling java

Access Java methods in C/C++
Access methods of Java parent classes in
C/C++ Access/modify Java variables in C/C++

Access C/C++ methods in Java
Access/modify C/C++ variables in Java

// DynamicReg.java

package com.android.javacpp;

import android.util.Log;

public class DynamicReg {
    
    
    private String  TAG = "JC_DynamicReg";

    public native String stringFromJNI();
    public static native int add(int a, int b);

    public int JavaInt = 10;
    public void JavaMethod() {
    
    
//        System.out.println("Hello from Java!");
        Log.d(TAG, "Java print hello world");
    }

    public native void JNIMethod();

    public void DynamicRegTest()
    {
    
    
        Log.d(TAG, "stringFromJNI: " + stringFromJNI());
        Log.d(TAG, "add (100, 500) " + add(100,500));

        Log.d(TAG, "JNIMehod called");
        JNIMethod();

    }
}

// DynamicReg.cpp

//
// Created by Administrator on 2023/7/6.
//

#include "DynamicReg.h"
std::string DynamicReg::myString = "Hello from c++";


jstring DynamicReg::stringFromJNI(JNIEnv *env, jobject instance) {
    
    
    jint version = env->GetVersion();
    LOGD("JNI version is : %x", version);

    return env->NewStringUTF(myString.c_str());
}

jint DynamicReg::JNIadd(JNIEnv *env, jclass clazz, jint a, jint b) {
    
    
    return a + b;
}

jint DynamicReg::RegisterNatives(JNIEnv *env) {
    
    
    jclass clazz = env->FindClass("com/android/javacpp/DynamicReg");
    if (clazz == NULL) {
    
    
        LOGE("could't find class: com/android/javacpp/DynamicReg");
        return JNI_ERR;
    }
    JNINativeMethod methods_MainActivity[] = {
    
    
            {
    
    "stringFromJNI", "()Ljava/lang/String;", (void *) stringFromJNI},
            {
    
    "add",           "(II)I",                (void *) JNIadd},
            {
    
    "JNIMethod", "()V", (void*) JNIMethod}

    };
    // int len = sizeof(methods_MainActivity) / sizeof(methods_MainActivity[0]);
    return env->RegisterNatives(clazz, methods_MainActivity,
                                sizeof(methods_MainActivity) / sizeof(methods_MainActivity[0]));
}

jint DynamicReg::JNI_OnLoad(JavaVM *vm, void *reserved) {
    
    
    JNIEnv *env = NULL;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
    
    
        LOGE("JNI_ERR");
        return JNI_ERR;
    }
    jint result = RegisterNatives(env);
    LOGD("RegisterNatives result: %x", result);
    return JNI_VERSION_1_6;
}

DynamicReg& DynamicReg::GetInstance()
{
    
    
    static DynamicReg instance;
    return instance;
}

void DynamicReg::JNIMethod(JNIEnv *env, jobject obj)
{
    
    
    // 访问Java层的变量
    jfieldID fieldId = env->GetFieldID(env->GetObjectClass(obj), "JavaInt", "I");
    jint myInt = env->GetIntField(obj, fieldId);
    printf("myInt = %d\n", myInt);
    LOGD("C++ get JavaInt = %d\n", myInt);

    // 调用Java层的方法
    jmethodID methodId = env->GetMethodID(env->GetObjectClass(obj), "JavaMethod", "()V");
    env->CallVoidMethod(obj, methodId);
}

Complete sample code download
JNI realizes mutual calling of java cpp

Guess you like

Origin blog.csdn.net/weixin_42445727/article/details/131559719