Jni 使用总结第二篇:c程序调用java

Jni使用总结二

c程序调用java

本文属于原创,转载请声明。

前言

众所周知,Java语言是将源代码编译成class文件的,并不能直接运行,需要在虚拟机中解析之后才能运行。个人理解jni的作用就是在我们的C程序中创建虚拟机,然后将java程序加载进来运行,根据我们的需求使用类的属性和方法。

1.java 程序

我们在c函数中将会对 age属性进行设置和调用sayhello方法并传入name
代码没啥可以说的,重点在c程序。

public class Hello{
    private int age;
    public static void main(String[] args) {
        System.out.println("Hello world!");
    }

    public  int sayhello(String name){
        System.out.println("Hello world!"+name);
        System.out.println("Hello world!"+age);
        return the data from java to c;
    }
    public void sayhello(){

    }
}

2.c 程序

a.创建虚拟机

写成函数的形式在main函数中调用。重点在与使用JNI_CreateJavaVM函数创建虚拟机

jint create_vm(JavaVM** jvm,JNIEnv** env) {  
        JavaVMInitArgs args;  
        JavaVMOption options[1];  
        args.version = JNI_VERSION_1_6;  
        args.nOptions = 1;  
        options[0].optionString = "-Djava.class.path=./";  //指明什么目录下查找类
        args.options = options;  
        args.ignoreUnrecognized = JNI_FALSE;  
        return JNI_CreateJavaVM(jvm, (void **)env, &args);  
}  
//main
        JavaVM* jvm;
    JNIEnv* env;
    if(create_vm(&jvm,&env))
    {
        printf("create vm error\n");
        return -1;
    }
b.查找获取类

使用FindClass查找我们在c程序中要调用的类,第二个参数指定要查找的类名

jclass cls;
cls = (*env)->FindClass(env, "Hello");
if (cls == NULL) {
    printf("can not find class\n");
    ret=-1;
    goto destroy;
}
c.实例化对象

实例化对象包括以下几个小点:

i.获取构造方法ID
//获取构造方法ID
        cid = (*env)->GetMethodID(env, cls,"<init>", "()V");
    if (cid == NULL){
        ret=-1;
        printf("can not get the construction method\n");
        goto destroy;
    }

使用GetMethodID获取构造方法 :

第一个参数:环境env

第二个参数:上文查找到的类cls

第三个参数:默认<init>

第四个参数:JNI字段描述符通过命令获取

javap -p -s Hello

使用javap生成如下:Signature就是JNI字段描述符

public class Hello {
  private int age;
    Signature: I
  public Hello();
    Signature: ()V

  public static void main(java.lang.String[]);
    Signature: ([Ljava/lang/String;)V

  public int sayhello(java.lang.String);
    Signature: (Ljava/lang/String;)I

  public void sayhello();
    Signature: ()V
}
ii.创建参数

: 如果调用没有参数的构造方法,此步骤可忽略。

iii.获取实例化对象

使用NewObject传入环境env,要实例化的类,类的构造方法ID,返回类的实例化对象。

//获取实例化对象
    jobj= (*env)->NewObject(env, cls,cid);
    if (cid == NULL){
        ret=-1;
        printf("can not create object\n");
        goto destroy;
    } 
d.设置类的属性

上文讲到要设置类的属性age的值,需要先通过GetFieldID找到属性的ID,才能使用SetIntField进行读取或者设置。

GetFieldID的用法类似GetMethodID

SetTypeField根据属性的类型修改Type的值。

//设置类的属性
        int age;
    jfid = (*env)->GetFieldID(env, cls, "age", "I");
    if (jfid == NULL){
        ret=-1;
        printf("can not get field ID\n");
        goto destroy;
    } 
    age=22;
    (*env)->SetIntField(env, jobj, jfid, age);//env,实例化对象,属性ID,要设置的内容
e.调用方法

i.获得调用方法的ID

//获得调用方法的ID
    mid = (*env)->GetMethodID(env, cls, "sayhello","(Ljava/lang/String;)I");
    if(mid==NULL)
    {
        printf("can not get the method\n");
        goto destroy;
    }

ii.调用方法

CallTypeMethod根据Java方法的返回值类型进行修改,参数分别是:
环境env;
实例化对象;
方法ID;
参数;

//调用方法
    result = (*env)->CallIntMethod(env, jobj, mid, jstr);
    printf("%d\n",result );

总结

上面两篇文章,介绍了java程序怎么调用c/c++库的函数;c程序怎么调用java方法;主要是从简单入手,希望起到抛砖引玉的作用。但文中对数据类型的转换没有详细的介绍,只是举例。期待第三篇对着方面进行详细的介绍。分享即所得。–manjia

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值