JNI的基本数据类型与C++对java对象的访问

5 篇文章 0 订阅

                    JNI的基本数据类型与C++对java对象的访问

    我使用的IDE是Android studio3.3 新建一个项目的时候选择 Native C++会自动创建一个带有Native 方法的项目,返回字符串“Hello From C++”

  MainActivity.java

 public native String stringFromJNI();

native-lib.cpp

extern "C" JNIEXPORT jstring JNICALL
Java_com_hz_jni02_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {

    return env->NewStringUTF("Hello from C++");

方法详解:每个native函数(C++),都至少有两个参数(JNIEvn *env ,jclass或者jobject)

       1、当native方法(java)方法为静态方法时:jobject代表nactive方法所属类的class对象(MainActivity.class)

        2、当native方法(java)方法为非静态方法时:jobject代表native方法所属的对象(MainActivity 对象)。

JNI 的基本数据类型:

java基本数据类型与JNI数据类型对应关系:

//java类型-->JNI类型

boolean-->jboolean

byte-->jbyte

char-->jchar

short-->jshort

int-->jint

long-->jlong

float-->jfloat

double-->jdouble

void-->void

 

java引用类型(对象)与JNI引用类型(对象)对应关系:

//java引用类型-->JNI引用类型

String -->jstring

Object-->jobject

//数组,基本数据 类型的数据

byte[]-->jByteArray

//对象数组

object[](String[])--> jobjectArray

C++对java对象的访问:

访问修改java类中的属性

        1、Java代码:

//声明变量
public String key="jack";
//编写一个native方法返回修改后的变量值
public native String accessField();
//返回修改完事的属性
String str=accessField();

2、C++代码:

extern "C"
JNIEXPORT jstring JNICALL
Java_com_hz_jni02_MainActivity_accessField(JNIEnv *env,
        jobject jobj) {
    //1、参数jobject   jobj是mainActivity对象,并非class
    jclass  cls=(*env).GetObjectClass(jobj);


    //2、jfieldID
    //1、jclass 2、属性名称 3、属性签名 
    jfieldID  fid=env->GetFieldID(cls,"key","Ljava/lang/String;");


    //3、jack >> super jack 将activity中变量key中的jack变成 super jack
    //获取key属性的值
    //Get<Type>Field
    jstring jstr= static_cast<jstring>(env->GetObjectField(jobj, fid));
    printf("jstr:%#x\n",&jstr);


    //4、jstring -> c字符串
    //isCopy 是否复制(true代表复制,false不复制)
    const char* c_str =env->GetStringUTFChars(jstr,JNI_FALSE);


    //5、拼接得到新的字符串
    char text[20] = "super ";
    strcat(text,c_str);


    //6、c字符串 ->jstring
    jstring new_jstr=env->NewStringUTF(text);


    //7修改key
    //Set<Type>Field
    env->SetObjectField(jobj,fid,new_jstr);
    printf("new_jstr:%#x\n", &new_jstr);


    return new_jstr;
}

属性签名对照表 就看这个属性的类型是什么样的

访问修改java类中的静态属性

        1、Java代码:

//定义一个int类型的静态变量
public static int count=1;
//访问静态属性的方法
public native void accessStaticField();
//调用
Log.d("MainActivity", "访问前count:" + count);
accessStaticField();
Log.d("MainActivity", "访问后count:" + count);

 2、C++代码:

extern "C"
JNIEXPORT void JNICALL
Java_com_hz_jni02_MainActivity_accessStaticField(JNIEnv *env, jobject instance) {
    //1、获取jClass
    jclass cls=(*env).GetObjectClass(instance);
    //2、获取jFieldId
    jfieldID fld=env->GetStaticFieldID(cls,"count","I");
    //3、GetStatic<Type>Field
    jint count=env->GetStaticIntField(cls,fld);
    count++;
    //修改
    //SetStatic<Type>Field
    env->SetStaticIntField(cls,fld,count);

  3、打印结果:

2019-04-24 16:08:42.370 8023-8023/MainActivity: 访问前count:1
2019-04-24 16:08:42.370 8023-8023/MainActivity: 访问后count:2

访问java方法

        1、Java代码

//1、定义一个方法  
//产生指定范围的随机数
public int genRandomInt(int max){
    Log.d("MainActivity", "执行了"+max);
    return new Random().nextInt(max);
}
//2、创建一个native方法
public native void accessMethod();
//3、调用native方法
accessMethod();

  2、C++代码

extern "C"
JNIEXPORT void JNICALL
Java_com_hz_jni02_MainActivity_accessMethod(JNIEnv *env, jobject instance) {


    // 1、获取jclass
    jclass cls=(*env).GetObjectClass(instance);
    //2、获取jMethodId
    // 参数内容1、jclass 2、方法名称 3、方法签名
    jmethodID mtd=env->GetMethodID(cls,"genRandomInt","(I)I");
    //调用这个方法
    //Call<Type>Method
    env->CallIntMethod(instance,mtd,200);
}

访问java静态方法

        1、Java代码

//1、创建一个方法,产生了一个UUID
public static String getUUID(){
    Log.d("MainActivity", "字符串被调用");
    return  randomUUID().toString();
}
//2、创建一个native方法
public native void accessStaticMethod();
//3、调用native方法
accessStaticMethod();

    2、C++代码

// 1、获取jclass
jclass cls=(*env).GetObjectClass(instance);
//2、获取jMethodId
jmethodID mtd=env->GetStaticMethodID(cls,"getUUID","()Ljava/lang/String;");
//3、调用
//Call<Type>Method
env->CallStaticObjectMethod(cls,mtd);

如果要访问构造方法

      1、java代码

//1、创建一个准备调用构造方法 的natvie方法
public native void accessConstructor();
//调用native方法
accessConstructor();

  2、C++代码

extern "C"
JNIEXPORT void JNICALL
Java_com_hz_jni02_MainActivity_accessConstructor(JNIEnv *env, jobject instance) {
    //访问构造方法
    //使用java.util.Date产生一个当前的时间戳
   jclass cls=(*env).FindClass("java/util/Date");
   /*jmethodId*/
    jmethodID  constructor_mid=env->GetMethodID(cls,"<init>","()V");
    //实例化一个Date对象
    jobject dateObj=env->NewObject(cls,constructor_mid);
    /*调用getTime方法*/
    jmethodID mid=env->GetMethodID(cls,"getTime","()J");


    jlong  time=env->CallLongMethod(dateObj,mid);
    printf("\ntime:%lld\n",time);


}

数组的返回:

    1、java代码

//定义一个native方法。
public native int[] getArray(int length);
//调用
int[] arrays=getArray(10);

    2、C++代码

extern "C"
JNIEXPORT jintArray JNICALL
Java_com_hz_jni02_MainActivity_getArray(JNIEnv *env, jobject instance,jint length) {
    //创建一个指定大小的数组
    jintArray array=env->NewIntArray(length);
    jint* elms=env->GetIntArrayElements(array,NULL);
    int i = 0;
    for (; i < length; i++){
        elms[i] = i;
    }
    env->ReleaseIntArrayElements(array,elms,0);
    return array;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值