1 访问构造方法
c代码
JNIEXPORT jobject JNICALL Java_com_yeliang_JniTest_accessConstructor(JNIEnv *env, jobject jobj){
//1 根据全类名 找到jclass
jclass cls = (*env)->FindClass(env,"java/util/Date");
//2 jmethodID
jmethodID construct_mid = (*env)->GetMethodID(env,cls,"<init>","()V");
//3 实例化一个Date对象
jobject date_obj = (*env)->NewObject(env,cls,construct_mid);
//4 找到getTime)()方法
jmethodID mid = (*env)->GetMethodID(env,cls,"getTime","()J");
//4 调用对象中的方法
jlong time = (*env)->CallLongMethod(env,date_obj,mid);
printf("time:%lld\n",time);
return date_obj;
}
找到方法对应的签名: 配置了环境变量后 使用如下命令 javap -p -s 全类名
java代码
public native Date accessConstructor();
public static void main(String[] args) {
JniTest jniTest = new JniTest();
jniTest.accessConstructor();
}
2 调用父类的方法
c代码
JNIEXPORT void JNICALL Java_com_yeliang_JniTest_accessNonvirtualMethod(JNIEnv *env, jobject jobj){
//1 jclass
jclass cls = (*env)->GetObjectClass(env,jobj);
//2 获取Man对象(对象)
jfieldID fid = (*env)->GetFieldID(env, cls, "human", "Lcom/yeliang/Human;");
//3 jobject
jobject human_obj = (*env)->GetObjectField(env,jobj,fid);
//4 Human类 jclass
jclass human_cls = (*env)->FindClass(env,"com/yeliang/Human");
//5 jmethidID 执行sayHi方法
jmethodID mid = (*env)->GetMethodID(env,human_cls,"sayHi","()V");
//6 调用父类的方法
(*env)->CallNonvirtualObjectMethod(env,human_obj,human_cls,mid);
}
查看方法签名的方法
java代码
public class Human {
public void sayHi(){
System.out.println("hello i am human");
}
}
public class Man extends Human {
public void sayHi() {
System.out.println("hi i am man");
}
}
打印结果
hello i am human
3 中文乱码问题
c代码
JNIEXPORT jstring JNICALL Java_com_yeliang_JniTest_accessChineseChar(JNIEnv *env, jobject jobj, jstring str){
//输出
char *c_str = (*env)->GetStringUTFChars(env,str,JNI_FALSE);
printf("%s\n",c_str);
}
java代码
public native void accessChineseChar(String string);
public static void main(String[] args) {
JniTest jniTest = new JniTest();
jniTest.accessChineseChar("德玛西亚必胜!");
}
打印结果
寰风帥瑗夸簹蹇呰儨锛?
修改后 把字符串从java传到c,在从c中传到java
c代码
JNIEXPORT jstring JNICALL Java_com_yeliang_JniTest_accessChineseChar(JNIEnv *env, jobject jobj,jstring jstr){
//输出
/*char *c_str = (*env)->GetStringUTFChars(env,str,JNI_FALSE);
printf("%s\n",c_str);*/
char *c_str = (*env)->GetStringUTFChars(env,jstr,JNI_FALSE);
//char *c_str = "德玛西亚必胜!";
//2 jclass-->String类
jclass str_cls = (*env)->FindClass(env, "java/lang/String");
//3 构造方法 jmethodID
jmethodID construct_mid = (*env)->GetMethodID(env, str_cls, "<init>", "([BLjava/lang/String;)V");
//4 jbyteArray
jbyteArray bytes = (*env)->NewByteArray(env, strlen(c_str));
//bytes赋值
(*env)->SetByteArrayRegion(env, bytes, 0, strlen(c_str), c_str);
//6 编码格式 jstring
jstring charsetName = (*env)->NewStringUTF(env, "UTF-8");
//7 调用构造函数,返回编码之后的jstring
return (*env)->NewObject(env, str_cls, construct_mid, bytes, charsetName);
}
java代码不变
打印结果
德玛西亚必胜!
上面是把字符串从java中传到c中,在从c中传到java的过程。主要是利用在c中调用java中String的构造方法来完成字符格式的转换
public String(byte bytes[], String charsetName)
throws UnsupportedEncodingException {
this(bytes, 0, bytes.length, charsetName);
}
直接把c中字符串传到java
JNIEXPORT jstring JNICALL Java_com_yeliang_JniTest_accessChineseChar(JNIEnv *env, jobject jobj,jstring jstr){
//输出
/*char *c_str = (*env)->GetStringUTFChars(env,str,JNI_FALSE);
printf("%s\n",c_str);*/
//char *c_str = (*env)->GetStringUTFChars(env,jstr,JNI_FALSE);
char *c_str = "德玛西亚必胜!";
//2 jclass-->String类
jclass str_cls = (*env)->FindClass(env, "java/lang/String");
//3 构造方法 jmethodID
jmethodID construct_mid = (*env)->GetMethodID(env, str_cls, "<init>", "([BLjava/lang/String;)V");
//4 jbyteArray
jbyteArray bytes = (*env)->NewByteArray(env, strlen(c_str));
//bytes赋值
(*env)->SetByteArrayRegion(env, bytes, 0, strlen(c_str), c_str);
//6 编码格式 jstring
jstring charsetName = (*env)->NewStringUTF(env, "GB2312");
//7 调用构造函数,返回编码之后的jstring
return (*env)->NewObject(env, str_cls, construct_mid, bytes, charsetName);
}
打印结果
德玛西亚必胜!
这此时在c中定义的char* str。然后传到java中。并改了字符编码格式。
4 把数组从java传到c中
c代码
int compare(int *a, int *b){
return (*a) - (*b);
}
JNIEXPORT void JNICALL Java_com_yeliang_JniTest_passArray(JNIEnv *env, jobject jobj, jintArray arr){
//1 jintArray ->jint指针 -> c int数组
jint *elems = (*env)->GetIntArrayElements(env,arr,NULL);
//2 数组的长度
int len = (*env)->GetArrayLength(env,arr);
//3 排序
qsort(elems,len,sizeof(jint),compare);
//4 同步
(*env)->ReleaseIntArrayElements(env,arr,elems,JNI_COMMIT);
}
java代码
public static void main(String[] args) {
JniTest jniTest = new JniTest();
int [] array = {1,2,4,2,5};
jniTest.passArray(array);
for(int i=0;i<array.length;i++){
System.out.println(array[i]);
}
}
打印结果
1 2 2 4 5
4 把数组从c传到java中
c代码
JNIEXPORT jarray JNICALL Java_com_yeliang_JniTest_getArray(JNIEnv *env, jobject jobj, jint len){
//1 创建一个指定大小的数组
jintArray jint_arr = (*env)->NewIntArray(env,len);
//2 jintArray ->jint指针 -> c int数组
jint *elems = (*env)->GetIntArrayElements(env,jint_arr,NULL);
int i = 0;
for (; i < len;i++){
elems[i] = i;
}
//3 同步
//0 , java数组进行更新,并且释放c/c++数组
//JNI_ABORT java数组不进行更新,但是释放c/c++数组
//JNI_CoMMIT, java数组进行更新,不释放c/c++数组(函数执行完 数组还是会释放)
(*env)->ReleaseIntArrayElements(env,jint_arr,elems,0);
return jint_arr;
}
java代码
public native int[] getArray(int size);
public static void main(String[] args) {
JniTest jniTest = new JniTest();
int [] array = jniTest.getArray(8);
for(int i=0;i<array.length;i++){
System.out.println(array[i]);
}
}
打印结果
0 1 2 3 4 5 6 7