JNI 之c/c++和Java交互,调用java成员

public class JniTest2 {

    //c访问非静态成员
    public String testField="hello...";
    //c修改java静态成员
    public static int time=78;
    //c访问java 方法
    public native void invokeJavaMethod();
    //c修改java 静态成员
    public native void modifyStaField();
    public native static String getProgress();
    public native String getStringFromC();
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String progress=getProgress();
        System.out.println("test=from c="+progress);
        JniTest2 t=new JniTest2();
        System.out.println("test c before=="+t.testField);
        String result=t.getStringFromC();
        System.out.println("test c after=="+result);
        System.out.println("===============静态成员修改==============");
        System.out.println("test=c beforestatic="+time);
        t.modifyStaField();
        System.out.println("test=c after static="+time);
        System.out.println("===============调用java方法==============");
        t.invokeJavaMethod();
    }
    static {
        //加载x64 .dll静态库
        System.loadLibrary("JNIDateType");
    }

    public int generateRandom(int seed) {
        System.out.println("test=java 方法被C调用了=");
        return new Random().nextInt(seed);
    }
}

下面是c/c++访问java 成员和方法

#define _CRT_SECURE_NO_WARNINGS
#include "jni_data_test_JniTest2.h"
#include<string.h>


//c返回java 层数据
JNIEXPORT jstring JNICALL Java_jni_1data_1test_JniTest2_getProgress
(JNIEnv *Env, jclass jcls){
    //Java函数在c层实现
    char *progress = "95";
    return (*Env)->NewStringUTF(Env,progress);
};

//c重写实现java方法
JNIEXPORT jstring JNICALL Java_jni_1data_1test_JniTest2_getStringFromC
(JNIEnv *Env, jobject jobj){
  //得到java 发射类
  jclass jobjclass= (*Env)->GetObjectClass(Env,jobj);
 //通过反射得到java 成员,注意最后一个参数是数据类型签名“L+类名(中间斜杠)”
  jfieldID jfield = (*Env)->GetFieldID(Env, jobjclass, "testField", "Ljava/lang/String;");
 //获取当前成员属性值
 jstring jfieldvalue = (*Env)->GetObjectField(Env,jobj,jfield);
 //注意:c无法修改jstring,进行转换char*,最后一个参数是否复制
 char *fieldValue = (*Env)->GetStringUTFChars(Env, jfieldvalue, NULL);
 strcat(fieldValue,"what the fuck!");
 //char * 转成 jstring 返回
 jstring result =(*Env)->NewStringUTF(Env,fieldValue);
 //修改java的成员值
 (*Env)->SetObjectField(Env,jobj,jfield,result);
 return result;
};

//c 调用java 方法
JNIEXPORT void JNICALL Java_jni_1data_1test_JniTest2_invokeJavaMethod
(JNIEnv *Env, jobject jobj){
    //反射java类
    jclass javaclass=(*Env)->GetObjectClass(Env,jobj);
    //获取方法id,方法签名 java工程bin目录 javap -s -p java全类名
    jmethodID methodId=(*Env)->GetMethodID(Env,javaclass,"generateRandom","(I)I");
    //调用方法
    jint value=(*Env)->CallIntMethod(Env,jobj,methodId,89);
    printf("c调用java方法结果==%d==\n",value);
};

//c 修改java静态成员
JNIEXPORT void JNICALL Java_jni_1data_1test_JniTest2_modifyStaField
(JNIEnv *Env, jobject jobj){
   jclass  javaclz= (*Env)->GetObjectClass(Env,jobj);
   //注意成员签名
   jfieldID staFieldId=(*Env)->GetStaticFieldID(Env,javaclz,"time","I");
   //jint 是long类型,可强转
  jint fieldValue= (*Env)->GetStaticIntField(Env,javaclz,staFieldId);
  fieldValue += 15;
  //修改完成设置static 成员
  (*Env)->SetStaticIntField(Env,javaclz,staFieldId,fieldValue);
};

运行效果如下,工作空间GBK和UTF8不协调乱码
这里写图片描述

总结:其中最值得注意的是,获取java 类里面所有成员签名的命令方式
//签名,进入 java工程bin目录 javap -s -p java全类名
见如下图中标红的,就是java 类中的成员的签名
da

c/c++有很多方法是没有的但Java有的,如果c/c++自己实现起来很不方便,不如调用java现有的,这也是面向对象思想体现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值