JNI笔记 C访问Java构造方法,父类方法,中文乱码,C向Java中传入数组

来源:互联网 发布:陈忠徐紫砂壶淘宝假货 编辑:程序博客网 时间:2024/05/20 10:51

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 把数组从java传到c中

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 
原创粉丝点击