JNI学习(二)调用java数据、字符串、数组,对象以及类

来源:互联网 发布:足球视频直播软件 编辑:程序博客网 时间:2024/06/03 19:09

在学习过调用原生函数来返回字符串以后,开始学习在原生方法中调用java中的资源,包括int型数据,string型数据,Array数组,object对象和class类,下面以此介绍。
1、调用int型数据
int型数据是最常用的数据类型之一,所以我从调用int型数据入手学习,非常简单
首先在MainActivity中声明本地方法

public native int intFromJNI();

注意返回值为int型即可,然后在.cpp文件中依照规则,编写本地方法名和方法内容

extern "C"JNIEXPORT jint JNICALLJava_com_seuic_ndkstudy_MainActivity_intFromJNI(        JNIEnv *env,        jobject  this ){    return 1;}

注意返回类型为jint,这是jni层和java中int的对应类型。
最后在MainActivity中使用TextView组件显示返回结果即可

        TextView tv1 = (TextView) findViewById(R.id.sample_text);        tv1.setText(intFromJNI()+"");

在应用中可以显示返回值为1

2、调用string型数据
同样,先声明本地方法

public native  String stringFromJNI(String prompt);

然后编写本地方法

extern "C"JNIEXPORT jstring JNICALLJava_com_seuic_ndkstudy_MainActivity_stringFromJNI(        JNIEnv *env,        jobject  this ,        jstring prompt){    const char *c_data = env->GetStringUTFChars(prompt,NULL);    int len_data = strlen(c_data);    char cc_data[len_data];    strcpy(cc_data, c_data);    env->ReleaseStringUTFChars(prompt,c_data);    return env->NewStringUTF(cc_data);}

这里本地方法的作用是调用java中的字符串prompt,将其复制到本地字符串数组cc_data中,然后释放调用的java字符串资源,最后将cc_data作为字符串返回至java层。首先用GetStringUTFChars(prompt,NULL)将prompt字符串地址传递给c_data;通过strlen()方法获取字符串的长度并保存在len_data中;通过strcpy函数将字符串从c_data中地址位置复制到cc_data字符数组中;通过ReleaseStringUTFChars(prompt,c_data)函数释放调用的资源;最后通过env->NewStringUTF(cc_data)函数生成新数组并返回。
接着在MainActivity中调用TextView组件显示返回的字符串,验证成功

3、调用数组
数组的调用跟字符串调用比较接近,下面进行实现,声明本地方法

private  native int sumArray(int[] array,int arrLength);

本地方法程序如下

extern "C"JNIEXPORT jint JNICALLJava_com_seuic_ndkstudy_MainActivity_sumArray(        JNIEnv *env,        jobject /* this */,        jintArray array,        jint arrayLength){//    jint buf[arrayLength];//    env->GetIntArrayRegion(array,0,arrayLength,buf);    jint *carr;    carr = env->GetIntArrayElements(array,NULL);    int length = env->GetArrayLength(array);    if(carr == NULL)    {        return 0;    }    int sum = 0;    for(int i=0 ; i<arrayLength ; i++)    {//        sum += buf[i];        sum += carr[i];    }    env->ReleaseIntArrayElements(array,carr,0);    return length;}

在本地方法中,在java调用中即传入了数组长度arrayLength,方便在本地方法中处理数组数据,后来为了更方便使用,在本地方法中使用

int length = env->GetArrayLength(array);

来获取传入的数组长度,也验证可行。

env->GetIntArrayRegion(array,0,arrayLength,buf);

方法将array数组中,从0到arrayLength长度的数据传入buf数组。
在调用结束之后使用

env->ReleaseIntArrayElements(array,carr,0);

来释放占用的资源。
进行求和结束后,返回数组元素之和,在MainActivity中显示,验证成功。

4、调用object对象
调用int型数据,string型字符串,数组都比较简单,下面进行调用对象的习,首先新建一个DataProces类,在此类中声明本地方法

private native int GetJavaData();

对编写本地方法

extern "C"JNIEXPORT jint JNICALLJava_com_seuic_ndkstudy_DataProcess_GetJavaData(        JNIEnv *env,        jobject  obj ){//    jclass cls = env->GetObjectClass(obj);    jclass  cls = env->FindClass("com/seuic/ndkstudy/DataProcess");    if(cls == NULL)        return 0;    jmethodID jmethodID1 = env->GetMethodID(cls,"DataSum","()V");    env->CallVoidMethod(obj,jmethodID1);    return 1;}

本地方法的作用是用过传入的object对象,查找到相应的类,并调用该类中的一个方法。
在DataProcess类中实现如下

    public DataProcess(int newData)    {        this.data1 = newData;        GetJavaData();    }    public void DataSum()    {        this.data1 += 1;    }

最后在MainActivity中显示,验证成功。

5、调用类
在jni中调用类有几种方式,我验证了两种,第一种通过传入的对象来找到对应的类,另一种通过路径直接找到类。

//    jclass cls = env->GetObjectClass(obj);    jclass  cls = env->FindClass("com/seuic/ndkstudy/DataProcess");

完整代码如下

extern "C"JNIEXPORT jobject JNICALLJava_com_seuic_ndkstudy_MainActivity_GetJavaClass(        JNIEnv *env,//        jobject  object)        jclass jclass1){//    jclass cls = env->GetObjectClass(obj);    jclass  cls = env->FindClass("com/seuic/ndkstudy/DataProcess");    if(cls == NULL)        return 0;    jmethodID jmethodID1 = env->GetMethodID(cls,"DataSum","()V");    jmethodID jmethodID2 = env->GetMethodID(cls,"<init>","(I)V");    jobject obj = env->NewObject(cls,jmethodID2,100);    env->CallVoidMethod(obj,jmethodID1);    return obj;}

在调用java类之后,然后新建一个类的实例对象,然后返回对象,在MainActivity中声明如下

private native DataProcess GetJavaClass();

因为返回的是DataProcess类的对象,所以此处声明返回值也为DataProcess。验证返回成功,可以显示在jni中新建对象的属性值。

0 0