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

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 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值