1.对字符串的操作
1.先看java层的操作
public class JniDemo {
public String msg = "ABC";
// 操作字符串的第一种方式
public native void callCppFunction();
// 操作字符串的第二种方式
public native void callCppFunction1();
// 操作字符串的第三种方式
public native void callCppFunction2();
}
2.看native的操作,都有注释
extern "C"
JNIEXPORT void JNICALL
Java_com_univer_androidyellowbook_JniDemo_callCppFunction(JNIEnv *env, jobject thiz) {
// 第一种操作java层的字符串
// 先获取msg的field_id
jfieldID fid_msg = env->GetFieldID(env->GetObjectClass(thiz), "msg", "Ljava/lang/String;");
// 获取msg的对象
jstring j_msg = (jstring) env->GetObjectField(thiz, fid_msg);
// 获取字符串的指针
const jchar *jstr = env->GetStringChars(j_msg, NULL);
// 转为宽字符串
wstring wstr((const wchar_t *) jstr);
// 释放指针
env->ReleaseStringChars(j_msg, jstr);
// 将字符串进行倒序
reverse(wstr.begin(), wstr.end());
// 获取倒叙后的薪字符串
jstring j_new_str = env->NewString((const jchar*)wstr.c_str(), (jint)wstr.size());
// 将字符串设置在变量中
env->SetObjectField(thiz, fid_msg, j_new_str);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_univer_androidyellowbook_JniDemo_callCppFunction1(JNIEnv *env, jobject thiz) {
// 先获取msg的field_id
jfieldID fid_msg = env->GetFieldID(env->GetObjectClass(thiz), "msg", "Ljava/lang/String;");
// 获取msg的对象
jstring j_msg = (jstring) env->GetObjectField(thiz, fid_msg);
// 第二种操作java层的字符串
// 先获取字符串指针
const jchar *jstr = env->GetStringCritical(j_msg, NULL);
// 转为宽字符串
wstring wstr((const wchar_t *) jstr);
// 释放指针
env->ReleaseStringCritical(j_msg, jstr);
// 将字符串进行倒序
reverse(wstr.begin(), wstr.end());
// 获取倒叙后的薪字符串
jstring j_new_str = env->NewString((const jchar *) wstr.c_str(), (jint) wstr.size());
// 将字符串设置在变量中
env->SetObjectField(thiz, fid_msg, j_new_str);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_univer_androidyellowbook_JniDemo_callCppFunction2(JNIEnv *env, jobject thiz) {
// 第三种操作字符串
// 先获取msg的field_id
jfieldID fid_msg = env->GetFieldID(env->GetObjectClass(thiz), "msg", "Ljava/lang/String;");
// 获取msg的对象
jstring j_msg = (jstring) env->GetObjectField(thiz, fid_msg);
// 获取字符串的长度
jsize len = env->GetStringLength(j_msg);
// 生成长度为len的字符串指针
jchar *jstr = new jchar(len + 1);
// c++中字符串以\0结尾
jstr[len] = L'\0';
// 将字符串j_msg复制到jstr中
env->GetStringRegion(j_msg, 0, len, jstr);
// 转为宽字符
wstring wstr((const wchar_t *) jstr);
// 释放指针
delete[] jstr;
// 将字符串进行倒序
reverse(wstr.begin(), wstr.end());
// 获取倒叙后的薪字符串
jstring j_new_str = env->NewString((const jchar *) wstr.c_str(), (jint) wstr.size());
// 将字符串设置在变量中
env->SetObjectField(thiz, fid_msg, j_new_str);
}
3.我们在active里添加一个button,并添加一个事件
Button button3 = findViewById(R.id.button3);
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.i(Tag, "start call native3");
// jniDemo.sayHello();
jniDemo.processArray();
JniDemo.initNative();
Log.i(Tag, Arrays.toString(jniDemo.arrays));
// tv2.setText(jniDemo.msg);
}
});
这样每次调用都可以根据按钮来操作,挺方便的
总结一下
获取字符串对象的属性
1.获取field_id
2.根据field_id获取对象
3.获取对象得指针
4.根据指针转为宽字符,为什么是宽字符,因为java里得编码是utf16,一个字符占两个字节,所以需要转为宽字节字符串
5.再给java层得对象的属性赋值