JNI的初步使用(二)

本文详细介绍了JNI的基本数据类型及C/C++访问Java的方法,包括访问类属性、静态属性、方法、构造方法,以及如何传入和返回数组等内容。

JNI基本数据类型,以及C,C++访问Java
Java代码,获取类的属性和静态属性,以及java的函数,构造方法,传入数组并排序,以及返回一个数组

public class JniTest {
    public String key="jason";

    public native static void getStringFromC();

    //访问属性,返回修改之后的属性内容
    public native String accessfield();

    public static void main(String[] args){
        JniTest t=new JniTest();
        System.out.println(t.accessfield());

    }
    //加载动态库
    static{
        System.loadLibrary("jni_study");
    }

}

.c文件

//每个native函数,都至少有两个参数(JNIEnv*,jclass或者jobject)
//1)当native方法为静态方法时:
//jclass 代表native方法所属类的class对象(JniTest.class)
//2)当native方法为非静态方法时:
//jobject 代表native方法所属的对象

//基本数据
//Java基本数据类型与JNI数据类型的映射关系
//Java类型->JNI类型->C类型

/*
boolean jboolean
byte jbyte;
char jchar;
short jshort;
int jint;
long jlong;
float jfloat;
double jdouble;
void void
*/

//引用类型(对象)
//String jstring
//object jobject
//数组,基本数据类型的数组
//byte[] jByteArray
//对象数组
//object[](String[]) jobjectArray

//修改属性key
JNIEXPORT jstring JNICALL Java_com_skyl_jni_JniTest_accessField
(JNIEnv *env, jobject jobj){
    //jobj是t对象,JniTest.class
    jclass cls = (*env)->GetObjectClass(env, jobj);
    //jfieldID
    //属性名称,属性签名
    jfieldID fid = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");   

    //jason >> super jason
    //获取key属性的值
    //Get<Type>Field
    jstring jstr = (*env)->GetObjectField(env, jobj, fid);  
    printf("jstr:%#x\n",&jstr);

    //jstring -> c字符串
    //isCopy 是否复制(true代表赋值,false不复制)
    char *c_str = (*env)->GetStringUTFChars(env,jstr,JNI_FALSE);
    //拼接得到新的字符串
    char text[20] = "super ";
    strcat(text,c_str);

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

    //修改key
    //Set<Type>Field
    (*env)->SetObjectField(env, jobj, fid, new_jstr);

    printf("new_jstr:%#x\n", &new_jstr);

    return new_jstr;
}

访问静态属性

JNIEXPORT void JNICALL Java_com_skyl_jni_JniTest_accessStaticField
(JNIEnv *env, jobject jobj){
    //jclass
    jclass cls = (*env)->GetObjectClass(env, jobj);
    //jfieldID
    jfieldID fid = (*env)->GetStaticFieldID(env, cls, "count", "I");
    //GetStatic<Type>Field
    jint count = (*env)->GetStaticIntField(env, cls, fid);
    count++;
    //修改
    //SetStatic<Type>Field
    (*env)->SetStaticIntField(env,cls,fid,count);
}

2.访问java方法

JNIEXPORT void JNICALL Java_com_dongnaoedu_jni_JniTest_accessMethod
(JNIEnv *env, jobject jobj){
    //jclass
    jclass cls = (*env)->GetObjectClass(env, jobj);
    //jmethodID
    jmethodID mid = (*env)->GetMethodID(env, cls, "genRandomInt", "(I)I");
    //调用
    //Call<Type>Method
    jint random = (*env)->CallIntMethod(env, jobj, mid, 200);
    printf("random num:%ld",random);

    //.....
}

静态方法

JNIEXPORT void JNICALL Java_com_skyl_jni_JniTest_accessStaticMethod
(JNIEnv *env, jobject jobj){
    //jclass
    jclass cls = (*env)->GetObjectClass(env, jobj);
    //jmethodID 
    jmethodID mid = (*env)->GetStaticMethodID(env, cls, "getUUID", "()Ljava/lang/String;");

    //调用
    //CallStatic<Type>Method
    jstring uuid = (*env)->CallStaticObjectMethod(env, cls, mid);

    //随机文件名称 uuid.txt
    //jstring -> char*
    //isCopy JNI_FALSE,代表java和c操作的是同一个字符串
    char *uuid_str = (*env)->GetStringUTFChars(env, uuid, JNI_FALSE);
    //拼接
    char filename[100];
    sprintf(filename, "D://%s.txt",uuid_str);
    FILE *fp = fopen(filename,"w");
    fputs("i love jason", fp);
    fclose(fp);
}

访问构造方法

//使用java.util.Date产生一个当前的时间戳
JNIEXPORT jobject JNICALL Java_com_skyl_jni_JniTest_accessConstructor
(JNIEnv *env, jobject jobj){
    jclass cls = (*env)->FindClass(env, "java/util/Date");
    //jmethodID
    jmethodID constructor_mid = (*env)->GetMethodID(env, cls, "<init>", "()V");
    //实例化一个Date对象
    jobject date_obj = (*env)->NewObject(env, cls, constructor_mid);
    //调用getTime方法
    jmethodID mid = (*env)->GetMethodID(env, cls, "getTime", "()J");
    jlong time = (*env)->CallLongMethod(env, date_obj, mid);

    printf("\ntime:%lld\n",time);

    return date_obj;
}

传入数组并排序

JNIEXPORT void JNICALL Java_com_skyl_jni_JniTest_giveArray
(JNIEnv *env, jobject jobj, jintArray arr){
    //jintArray -> jint指针 -> c int 数组
    jint *elems = (*env)->GetIntArrayElements(env, arr, NULL);
    //printf("%#x,%#x\n", &elems, &arr);

    //数组的长度
    int len = (*env)->GetArrayLength(env, arr);
    //排序
    qsort(elems, len, sizeof(jint), compare);   

    //同步
    (*env)->ReleaseIntArrayElements(env, arr, elems, JNI_COMMIT);
}

返回一个数组


JNIEXPORT jintArray JNICALL Java_com_skyl_jni_JniTest_getArray(JNIEnv *env, jobject jobj, jint len){
    //创建一个指定大小的数组
    jintArray jint_arr = (*env)->NewIntArray(env, len);
    jint *elems = (*env)->GetIntArrayElements(env, jint_arr, NULL); 
    int i = 0;
    for (; i < len; i++){
        elems[i] = i;
    }

    //同步
    (*env)->ReleaseIntArrayElements(env, jint_arr, elems, 0);   

    return jint_arr;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值