1 1 int 基本类型 , String 引用对象类型, int[] array 类型 String [] 引用对象数组类型
public native void testArrayAction(int count, String textInfo, int[] ints, String[] strs); // String引用类型,玩数组
public void test01(View view) {
int[] ints = new int[]{18,28,38,48,58,68}; // 基本类型的数组
String[] strs = new String[]{"小龙","小杰","小霸"}; // 对象类型的数组
testArrayAction(99, "你好", ints, strs);
for (int anInt : ints) {
Log.i("info", "Java test01: anInt:" + anInt);
}
for (String item : strs) {
Log.i("info", "Java test01: strings:" + item);
}
}
extern "C"
JNIEXPORT void JNICALL
Java_com_cn_mynativestudy_MainActivity_testArrayAction(
JNIEnv *env,
jobject thiz,
jint count,
jstring text_info,
jintArray ints,
jobjectArray strs) {
// C++ jint 对应 java int
// C++ jstring 对应 java String 或 Object
// C++ jintArray 对应 java int[]
// C++ jobjectArray 对应 java String[] 或 Object []
//1 JNI 中 jint 可以直接赋值 给 c++ 中 int
int c_int = count ;
LOGI("int = %d",c_int);
const char * c_string1 = env->GetStringUTFChars(text_info,NULL);
LOGI("string1 = %s",c_string1);
char * c_string2 = const_cast<char *>(env->GetStringUTFChars(text_info, NULL));
LOGI("string2 = %s",c_string2);
env->ReleaseStringUTFChars(text_info,c_string1);
env->ReleaseStringUTFChars(text_info,c_string2);
int * intArrays = env->GetIntArrayElements(ints ,NULL);
for (int i = 0; i < env->GetArrayLength(ints); ++i) {
*(intArrays + i)+1;
LOGI("ints[%d] = %d",i,*(intArrays +i));
}
/**
* 刷新 java 层 数据
* 0: 刷新Java数组,并 释放C++层数组
* JNI_COMMIT: 只提交 只刷新Java数组,不释放C++层数组
* JNI_ABORT: 只释放C++层数组
*/
env->ReleaseIntArrayElements(ints,intArrays,0);
jsize str_size = env->GetArrayLength(strs);
for (int i = 0; i <str_size; ++i) {
jstring j_str = static_cast<jstring>(env->GetObjectArrayElement(strs , i));
const char * item = env->GetStringUTFChars(j_str,NULL);
LOGI("strs[%d] = %s",i,item);
env->ReleaseStringUTFChars(j_str,item);
}
}
2 传递引用类型,传递对象
public native void putObject(Student student, String str); // 传递引用类型,传递对象
public void test02(View view) {
Student student = new Student(); // Java new
student.name = "史泰龙";
student.age = 88;
putObject(student, "九阳神功");
}
extern "C"
JNIEXPORT void JNICALL
Java_com_cn_mynativestudy_MainActivity_putObject(JNIEnv *env, jobject thiz, jobject student,
jstring str) {
jclass j_student = env->GetObjectClass(student);
char * classpath = "com/cn/mynativestudy/c19/Student";
jclass j_student2 = env->FindClass(classpath);
jmethodID j_setName1 = env->GetMethodID(j_student,"setName", "(Ljava/lang/String;)V");
jmethodID j_setName2 = env->GetMethodID(j_student2,"setName", "(Ljava/lang/String;)V");
jmethodID j_getName1 = env->GetMethodID(j_student,"getName", "()Ljava/lang/String;");
jmethodID j_getName2 = env->GetMethodID(j_student2,"getName", "()Ljava/lang/String;");
jstring name1 = env->NewStringUTF("哇啊啊");
env->CallVoidMethod(student,j_setName1,name1);
jstring j_getname1 = static_cast<jstring>(env->CallObjectMethod(student, j_getName1));
char * c_getname1 = const_cast<char *>(env->GetStringUTFChars(j_getname1, NULL));
LOGI("c_getname1 = %s",c_getname1);
jstring name2 = env->NewStringUTF("呼哈哈");
env->CallVoidMethod(student,j_setName2,name2);
jstring j_getname2 = static_cast<jstring>(env->CallObjectMethod(student, j_getName2));
char * c_getname2 = const_cast<char *>(env->GetStringUTFChars(j_getname2, NULL));
LOGI("c_getname2 = %s",c_getname2);
jmethodID showInfo = env->GetStaticMethodID(j_student, "showInfo", "(Ljava/lang/String;)V");
jstring jstringValue = env->NewStringUTF("我是C++");
env->CallStaticVoidMethod(j_student, showInfo, jstringValue);
}
3 通过包名创建对象
public native void insertObject();
public void test03(View view) {
insertObject();
}
extern "C"
JNIEXPORT void JNICALL
Java_com_cn_mynativestudy_MainActivity_insertObject(JNIEnv *env, jobject thiz) {
char * classpath = "com/cn/mynativestudy/c19/Student";
jclass j_student_class = env->FindClass(classpath);
jmethodID j_setName1 = env->GetMethodID(j_student_class,"setName", "(Ljava/lang/String;)V");
jstring name1 = env->NewStringUTF("哇啊啊");
// AllocObject 只实例化对象,不会调用对象的构造函数
jobject j_student_obj = env->AllocObject(j_student_class);
env->CallVoidMethod(j_student_obj,j_setName1,name1);
char * person_class_path = "com/cn/mynativestudy/c19/Person";
jclass j_person_class = env->FindClass(person_class_path);
jmethodID j_setStudent = env->GetMethodID(j_person_class,"setStudent", "(Lcom/cn/mynativestudy/c19/Student;)V");
jobject j_person_obj = env->AllocObject(j_person_class);
env->CallVoidMethod(j_person_obj,j_setStudent,j_student_obj);
jmethodID j_static_putStudent = env->GetStaticMethodID(j_person_class,"putStudent","(Lcom/cn/mynativestudy/c19/Student;)V");
env->CallStaticVoidMethod(j_person_class,j_static_putStudent,j_student_obj);
env->DeleteLocalRef(j_student_obj);
env->DeleteLocalRef(j_student_class);
env->DeleteLocalRef(j_person_obj);
env->DeleteLocalRef(j_person_class);
}
4 测试引用
public native void testQuote(); // 测试引用
public void test04(View view) {
testQuote();
}
jclass dogClass; // 你以为这个是全局引用,实际上他还是局部引用
extern "C"
JNIEXPORT void JNICALL
Java_com_cn_mynativestudy_MainActivity_testQuote(JNIEnv *env, jobject thiz) {
if (NULL == dogClass) {
/*const char * dogStr = "com/derry/as_jni_project/Dog";
dogClass = env->FindClass(dogStr);*/
// 升级全局引用: JNI函数结束也不释放,反正就是不释放,必须手动释放 -----
//相当于: C++ 对象 new、手动delete
const char * dogStr = "com/cn/mynativestudy/c19/Dog";
jclass temp = env->FindClass(dogStr);
dogClass = static_cast<jclass>(env->NewGlobalRef(temp)); // 提升全局引用
// 记住:用完了,如果不用了,马上释放,C C++ 工程师的赞美
env->DeleteLocalRef(temp);
}
jmethodID method1 = env->GetMethodID(dogClass,"<init>","()V");
jobject obj1 = env->NewObject(dogClass,method1);
jmethodID method2 = env->GetMethodID(dogClass,"<init>","(I)V");
obj1 = env->NewObject(dogClass,method2,100);
jmethodID method3 = env->GetMethodID(dogClass,"<init>","(II)V");
obj1 = env->NewObject(dogClass,method3,200,300);
env->DeleteLocalRef(obj1);
}
5 释放全局引用
public native void delQuote(); // 释放全局引用
public void test05(View view) {
delQuote(); // 必须释放全局引用
}
extern "C"
JNIEXPORT void JNICALL
Java_com_cn_mynativestudy_MainActivity_delQuote(JNIEnv *env, jobject thiz) {
if (dogClass != NULL) {
LOGE("全局引用释放完毕,上面的按钮已经失去全局引用,再次点击会报错");
env->DeleteGlobalRef(dogClass);
dogClass = NULL; // 最好给一个NULL,指向NULL的地址,不要去成为悬空指针,为了好判断悬空指针的出现
}
}
6 extern 关键字 ,方便扩展
extern int age; // 声明age
extern void show(); // 声明show函数