JNI心得 - (三)向本地代码传递数组

接着上一个例子java 调用本地代码 继续补充代码,这次看看本地代码如何接收java层数组。

首先在MainActivity.java 添加如下代码声明

    public native void stringArray(String []strArr);
    public native void floatArray(float []fArray);
    public native void boolArray(boolean[] bArray);

native关键字会告诉编译器这是一个本地方法,不需要检查该方法的在java层的实现。进入项目根目录然后执行如下命令进入目标目录(我用的是Ubuntu系统,所以用的cd命令,其他系统进入相应目录并在该目录开一个终端即可)

cd app/src/main/java

javah 生成header文件

javah -jni com.example.test.jnitest.MainActivity

执行后在同级目录下会生成一个后缀名为.h的文件

将这个文件移到到cpp文件夹下,将.h后缀名改为.cpp ,并将内容的函数声明改为函数定义即

JNIEXPORT jstring JNICALL Java_com_example_test_jnitest_MainActivity_stringFromJNI
  (JNIEnv *, jobject){

}


JNIEXPORT void JNICALL Java_com_example_test_jnitest_MainActivity_stringArray
  (JNIEnv *, jobject, jobjectArray){

}


JNIEXPORT void JNICALL Java_com_example_test_jnitest_MainActivity_floatArray
  (JNIEnv *, jobject, jfloatArray){

}

JNIEXPORT void JNICALL Java_com_example_test_jnitest_MainActivity_boolArray
  (JNIEnv *, jobject, jbooleanArray){
    
}

然后在函数定义内实现相应的逻辑,先拿

 

JNIEXPORT void JNICALL Java_com_example_test_jnitest_MainActivity_stringArray
  (JNIEnv *, jobject, jobjectArray){}

为例,先为函数添加型参

JNIEXPORT void JNICALL Java_com_example_test_jnitest_MainActivity_stringArray
  (JNIEnv *env, jobject object, jobjectArray stringArray){

}

然后获取string数组本地缓存,string 是一个对象类型,所以要用GetObjectArrayElement获取所对应的本地引用,在jni开发中会遇到多种GetXXXElement(XXX代表数据类型),他的作用是或去Java数据的本地引用与之对应的就是ReleaseXXX,他的作用是把本地数据反射给java,具体怎么实现的以后在做探究,这里先提一下。通过GetObjectArrayElement获取完数据后,需要将数据打印出来用以证明获取是否正确,打日志很简单,直接使用android的log系统即可,首先引入log头文件

#include <android/log.h>

然后在全局的地方写一个宏方便调用,也可以不写宏


#define LOG(...)  __android_log_print(ANDROID_LOG_INFO,"jnitest",__VA_ARGS__ )

这个版本的androidstudio已经在cmakelist里添加了log的库,所以不需要修改cmakelist.txt,在函数实现上直接调用即可,函数实现代码如下

JNIEXPORT void JNICALL Java_com_example_test_jnitest_MainActivity_stringArray
        (JNIEnv *env, jobject object, jobjectArray stringArray) {

    int count = env->GetArrayLength(stringArray);

    for (int i = 0; i < count; i++) {
        jobject item = env->GetObjectArrayElement(stringArray, i);

        const char *str = env->GetStringUTFChars((jstring) item, 0);

        LOG("index:%d string:%s", i, str);

        env->ReleaseStringUTFChars((jstring) item, str);

    }

}

本例中java层是这样调用的

  stringArray(new String[]{"A","B","C","D","E","F","G"});

运行结果

07-18 15:03:00.351 4425-4425/com.example.test.jnitest I/jnitest: index:0 string:A
    index:1 string:B
    index:2 string:C
    index:3 string:D
    index:4 string:E
    index:5 string:F
    index:6 string:G

 

获取float等基本类型的数据相较于string这样对象数组更简单些,这里只拿float数组为例,代码如下

JNIEXPORT void JNICALL Java_com_example_test_jnitest_MainActivity_floatArray
  (JNIEnv *env, jobject, jfloatArray floatArray){

   jfloat * array = env->GetFloatArrayElements(floatArray,0);

    int count = env->GetArrayLength(floatArray);

    for(int i=0;i<count;i++){

        LOG("index:%d float:%f", i, array[i]);
    }

    env->ReleaseFloatArrayElements(floatArray,array,0);
}

知道了以上几种方法就可以轻松获取java层的数据了

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值