1 静态注册的方式实现c/c++和java相互调用
C/C++中访问Java方法
C/C++中访问Java父类的方法
C/C++中访问/修改Java变量
Java中访问C/C++方法
Java中访问/修改C/C++变量
给出实现代码如下:
// 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 动态注册的方式实现c/c++调用java的方法/变量
C/C++中访问Java方法
C/C++中访问Java父类的方法
C/C++中访问/修改Java变量
Java中访问C/C++方法
Java中访问/修改C/C++变量
// 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); }
完整示例代码下载