在JNI中,本地代码(C/C++)中修改了Java对象的变量,并且将其传递回Java端,那么Java端会看到变量的修改,尝试以下两种方式进行修改:
-
添加native方法
data class MyData( var key:Int, var value:String ) class TestLib { companion object{ init { System.loadLibrary("jnitest") } } external fun modifyData(data:Int) external fun modifyMyData(data:MyData) } var data = 1 Log.i(TAG,"in = ${data}") testLib.modifyData(1) Log.i(TAG,"out = ${data}") var myData = MyData(1,"Hello") Log.i(TAG,"mydata in = ${myData.toString()}") testLib.modifyMyData(myData) Log.i(TAG,"mydata in = ${myData.toString()}")
-
C++
extern "C" JNIEXPORT void JNICALL Java_com_test_jnitest_TestLib_modifyData(JNIEnv *env, jobject thiz, jint data) { data = 2; } extern "C" JNIEXPORT void JNICALL Java_com_test_jnitest_TestLib_modifyMyData(JNIEnv *env, jobject thiz, jobject data) { jclass cls = env->GetObjectClass(data); jfieldID fieldKey = env->GetFieldID(cls, "key", "I"); // 获取变量的值 jint valueKey = env->GetIntField(data, fieldKey); // 修改变量的值 valueKey = 2; // 设置变量的新值 env->SetIntField(data, fieldKey, valueKey); jfieldID fieldValue = env->GetFieldID(cls, "value", "Ljava/lang/String;"); // 创建一个新的字符串 const char *newStr = "World"; jstring newString = env->NewStringUTF(newStr); // 设置实体类的String变量 env->SetObjectField(data, fieldValue, newString); }
日志打印:
I/MainActivity: in = 1 I/MainActivity: out = 1 I/MainActivity: mydata in = MyData(key=1, value=Hello) I/MainActivity: mydata in = MyData(key=2, value=World)
第一种方法虽然在JNI中将变量修改为2,但是在Java端仍然保持为1,这是因为在JNI中传递的是变量的值的副本,而不是引用。要在JNI中更改Java对象的变量,需要通过第二种传递对象的引用来实现,使用JNI函数获取和设置变量的值,成功地更改Java对象的变量。