上一篇文章是java如何调用c ,这篇文章是c如何调用 java
c调用java一共分为5步:
1:编写java native方法
2生成对应的头文件
3复制头文件到visule studio中
4查询方法和属性的签名,实现native方法
5编译生成.dll动态库,复制动态库到项目,然后调用
1:编写java native方法 以及要调用的方法
public native int ranNum();
// 产生随机数 要被native调用的方法
public int getRandomNum(int max) {
return (new Random()).nextInt(max);
}
2生成对应的头文件 在当前src目录下 使用命令行执行javah ,然后刷新项目,后会有头文件
3复制头文件到visule studio中
打开visual studio 创建新项目,把 jni.h jni_md.h(这两个文件在AndroidSDK中)以刚才及java工程生成的 com_ake_Test_test.h头文件一起拷贝到visual studio中
头文件右键->添加->现有项,之后如下图
4查询方法和属性的签名,实现native方法
在命令行中 java项目的bin 目录下执行javap 命令,然后在执行javap -s -p com.ake.Test.test(类的全名)
执行完javap -s -p之后如图 系统会把当前类所有的成员变量和属性方法的签名都列出来
在这个列表中我们找到
public int getRandomNum(int);
descriptor: (I)I
这个方法的签名就是 (I)I
然后打开visual studio 把java 生成的头文件复制进来
然后就是写个str.c 文件实现这个方法
5编译生成.dll动态库,复制动态库到项目,然后调用
在 Visual studio 中
选择工具栏中 debug--配置管理器--活动解决方案平台--新建--选择新平台--x64(我的电脑是64位)
配置项目生成.dll动态链接库
项目右键--常规--项目默认值--配置类型--动态库(.dll)
最后运行生成解决方法,然后复制根目录x64 --debug--.dll到java工程根目录
java调用 System.load("D:\\Android\\workspace3\\JniTest\\Project2.dll"); 这里要写绝对路径
这是个基本流程, 同样访问 c 访问java的成员变量也是一样的流程,只是在c代码的实现是不一样的
//c 访问java 成员属性的实现
JNIEXPORT jstring JNICALL Java_com_ake_Test_test_accessStaticField (JNIEnv *env, jobject obj){ //1 获取obj对象 jclass cls=(*env)->GetObjectClass(env, obj); //2获取属性id jfieldID id=(*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;"); // printf("jstr:%#x\n", &id); //获取属性值 jstring js=(*env)->GetObjectField(env, obj,id); // printf("jstr:%#x\n", &js); char * ori=(*env)->GetStringUTFChars(env, js, JNI_FALSE); // printf("new_jstr:%s\n", ori); //修改属性值 char* test = "mimi"; strcat(test,ori); //设置属性值 jstring s = (*env)->NewStringUTF(env, test); (*env)->SetObjectField(env, obj,id,s); return ori; }// c访问 java 方法的实现
JNIEXPORT jint JNICALL Java_com_ake_Test_test_ranNum (JNIEnv *env, jobject obj){ //获取class 对象 jclass cls= (*env)->GetObjectClass(env, obj); //获取方法ID 最后一个参数是我们在命令行中查到的方法的签名 jmethodID id= (*env)->GetMethodID(env, cls, "getRandomNum", "(I)I"); //调用该方法 jint i=(*env)->CallIntMethod(env, obj, id); return i; }他们的实现套路是一样的:
1获取jclass 对象
2获取 方法或者属性 id
3获取方法或者属性
4修改成员的值或返回方法的值
这获取方法或者属性想id时要求传入 签名 sign 下图有对应关系 如果想偷懒就用命令行在 java bin目录下 javap /javap -s -p看一xia
成员属性的签名可以直接抄就行了,方法的签名格式 (type)type 也就是 用()拼上参数的签名和返回值的签名 例如java 方法
public static String getUUID(){
return UUID.randomUUID().toString();
}
签名为 ()Ljava/lang/String;
public static void soutsom(){
System.out.println("soutsom 被调用!");
}
签名为 ()V
好了,谢谢大家能把它看完,有问题欢迎联系我!