博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android JNI 传递对象
阅读量:5265 次
发布时间:2019-06-14

本文共 7798 字,大约阅读时间需要 25 分钟。

JNI初步入门后,在传递数据的时候,遇到一个需求:有多个数据需要在Java与C代码之间进行传递。如果都做为函数参数传入,则函数很长很难看,并且多个数据的返回也不好实现。所以想到了把数据打包后传递。这在C语言中就是结构体,在Java中就是类了。我们要做的工作就是,先确定要传递的数据,然后相应在C与Java中定义相应的数据类型,然后通过JNI进行数据对应。下面以一个例程来逐步说明。为了更好的说明各种数据类型的转换示例,我们的数据包含整型、字符串、浮点数、字符、布尔值、数组。在Java端定义类:public class ParamInfo {    public boolean boolValue;    public char charValue;    public double doubleValue;    public int intValue;    public byte[] array;    public String str;}在C端定义结构体:typedef struct{    bool boolValue;    char charValue;    double doubleValue;    int intValue;    char array[255];    char str[255];}ParamInfo;jni接口中并不要求两边的变量名一致,或者类名与结构体名一致,只是我们为了逻辑清晰,最好将名称定义的一致,以便于在后续编写代码的过程中更好的将相应数据一一对应起来。在C代码中获取Java代码传递的参数:    以获取类中一个整型值为例:    //获取Java中的实例类ParamInfo    jclass jcInfo = env->FindClass("com/example/helloworld/ParamInfo");其中,com/example/helloworld 是包名对应路径,ParamInfo是包含数据接口的类名。    获取类中一个整型变量intValue的定义    jfieldID jfi = env->GetFieldID(jcInfo, "intValue", "I");    获取实例的变量intValue的值,其中jobj即参数中携带数据的对象:    paramInfo.intValue = env->GetIntField(jobj, jfi);在C代码中设置向Java端传递的参数:以传递结构体中一个整型值为例:    先设置结构体中整型值:paramInfo.intValue = 8;    获取Java中的实例类ParamInfo    jclass jcInfo = env->FindClass("com/example/helloworld/ParamInfo");其中com/example/helloworld 是包名对应路径,ParamInfo是包含数据接口的类名。    获取类中一个整型变量intValue的定义   jfieldID jfi = env->GetFieldID(jcInfo, "intValue", "I");    创建新的对象 jobject joInfo = env->AllocObject(jcInfo);    设置实例的变量intValue的值env->SetIntField(joInfo, jfi, paramInfo.intValue);    最后返回该对象return joInfo;其余数据类型值的访问,都是类似的步骤。注意 GetFieldID()的第3个参数的取值,是数据类型的签名标识,具体取值见下面表格:请查看下表:Java类型    符号boolean    Zbyte       Bchar       Cshort      Sint        Ilong       Lfloat      Fdouble     Dvoid       Vobject对象    LClassName; L类名;Arrays    [array-type [数组类型methods方法    (argument-types)return-type (参数类型)返回类型native代码知道这些了,就可以进行我们native代码的书写了,如下:// Java 类向C结构体类型转换JNIEXPORT jint JNICALL Java_com_example_helloworld_JniClient_setInfo  (JNIEnv *env, jobject jo, jobject jobj){    ParamInfo paramInfo;    //获取Java中的实例类ParamInfo    jclass jcInfo = env->FindClass("com/example/helloworld/ParamInfo");    //获取类中每一个变量的定义    //boolean boolValue    jfieldID jfb = env->GetFieldID(jcInfo, "boolValue", "Z");    //char charValue    jfieldID jfc = env->GetFieldID(jcInfo, "charValue", "C");    //double charValue    jfieldID jfd = env->GetFieldID(jcInfo, "doubleValue", "D");    //int intValue    jfieldID jfi = env->GetFieldID(jcInfo, "intValue", "I");    //byte[] array    jfieldID jfa = env->GetFieldID(jcInfo, "array", "[B");    //String str    jfieldID jfs = env->GetFieldID(jcInfo, "str", "Ljava/lang/String;");    //获取实例的变量boolValue的值    paramInfo.boolValue = env->GetBooleanField(jobj, jfb);    //获取实例的变量charValue的值    paramInfo.charValue = env->GetCharField(jobj, jfc);    //获取实例的变量doubleValue的值    paramInfo.doubleValue = env->GetDoubleField(jobj, jfd);    //获取实例的变量intValue的值    paramInfo.intValue = env->GetIntField(jobj, jfi);    //获取实例的变量array的值    jbyteArray ja = (jbyteArray)env->GetObjectField(jobj, jfa);    int  nArrLen = env->GetArrayLength(ja);    char *chArr = (char*)env->GetByteArrayElements(ja, 0);    memcpy(paramInfo.array, chArr, nArrLen);    //获取实例的变量str的值    jstring jstr = (jstring)env->GetObjectField(jobj, jfs);    const char* pszStr = (char*)env->GetStringUTFChars(jstr, 0);    strcpy(paramInfo.str, pszStr);    //日志输出    LOGI("paramInfo.array=%s, paramInfo.boolValue=%d, paramInfo.charValue=%c\n",           paramInfo.array, paramInfo.boolValue, paramInfo.charValue);    LOGI("paramInfo.doubleValue=%lf, paramInfo.intValue=%d,  paramInfo.str=%s\n",          paramInfo.doubleValue, paramInfo.intValue, paramInfo.str);    return 0;}// C结构体类型向Java 类转换JNIEXPORT jobject JNICALL Java_com_example_helloworld_JniClient_getInfo  (JNIEnv *env, jobject jo){    char chTmp[] = "Test array";    int nTmpLen = strlen(chTmp);    //将C结构体转换成Java类    ParamInfo paramInfo;    memset(paramInfo.array, 0, sizeof(paramInfo.array));    memcpy(paramInfo.array, chTmp, strlen(chTmp));    paramInfo.boolValue = true;    paramInfo.charValue = 'B';    paramInfo.doubleValue = 2.7182;    paramInfo.intValue = 8;    strcpy(paramInfo.str, "Hello from JNI");    LOGI("paramInfo.array=%s, paramInfo.boolValue=%d, paramInfo.charValue=%c\n",           paramInfo.array, paramInfo.boolValue, paramInfo.charValue);    //获取Java中的实例类    jclass jcInfo = env->FindClass("com/example/helloworld/ParamInfo");    //获取类中每一个变量的定义    //boolean boolValue    jfieldID jfb = env->GetFieldID(jcInfo, "boolValue", "Z");    //char charValue    jfieldID jfc = env->GetFieldID(jcInfo, "charValue", "C");    //double doubleValue    jfieldID jfd = env->GetFieldID(jcInfo, "doubleValue", "D");    //int intValue    jfieldID jfi = env->GetFieldID(jcInfo, "intValue", "I");    //byte[] array    jfieldID jfa = env->GetFieldID(jcInfo, "array", "[B");    //String str    jfieldID jfs = env->GetFieldID(jcInfo, "str", "Ljava/lang/String;");    //创建新的对象    jobject joInfo = env->AllocObject(jcInfo);    //给类成员赋值    env->SetBooleanField(joInfo, jfb, paramInfo.boolValue);    env->SetCharField(joInfo, jfc, (jchar)paramInfo.charValue);    env->SetDoubleField(joInfo, jfd, paramInfo.doubleValue);    env->SetIntField(joInfo, jfi, paramInfo.intValue);    //数组赋值    jbyteArray jarr = env->NewByteArray(nTmpLen);    jbyte *jby = env->GetByteArrayElements(jarr, 0);    memcpy(jby, paramInfo.array, nTmpLen);    env->SetByteArrayRegion(jarr, 0, nTmpLen, jby);    env->SetObjectField(joInfo, jfa, jarr);    //字符串赋值    jstring jstrTmp = env->NewStringUTF(paramInfo.str);    env->SetObjectField(joInfo, jfs, jstrTmp);    return joInfo;}Java端测试代码:        // 动态加载C库        System.loadLibrary("HelloWorld");        //进行对象的jni传递        ParamInfo paramInfoSet = new ParamInfo();               byte[] b = new byte[10];                for (int i = 0; i < 9; i++) {            b[i] = (byte) (i + 97);        }        paramInfoSet.array = b;             paramInfoSet.boolValue = false;        paramInfoSet.charValue = 'C';        paramInfoSet.doubleValue = 3.14;        paramInfoSet.intValue = 2016;               paramInfoSet.str = "Hello from Java";        Log.i("Hello", "log: to access lib");        JniClient.setInfo(paramInfoSet);        Log.i("Hello", "log: after setInfo");        //进行对象的jni接收        ParamInfo paramInfoGet = JniClient.getInfo();        Log.i("Hello", "log: paramInfoGet.boolValue=" + paramInfoGet.boolValue                 + " paramInfoGet.charValue=" + paramInfoGet.charValue                + " paramInfoGet.doubleValue=" + paramInfoGet.doubleValue);        Log.i("Hello", "log: paramInfoGet.intValue=" + paramInfoGet.intValue                 + " paramInfoGet.array=" + new String(paramInfoGet.array)                + " paramInfoGet.str=" + paramInfoGet.str);        //将收到的字符串显示到界面上        TextView tv_say_hello = (TextView) findViewById(R.id.tv_say_hello);        tv_say_hello.setText(paramInfoGet.str);        Log.i("Hello", "log: finish");    最后输出的日志信息:06-25 17:04:25.740: I/Hello(19039): log: to access lib06-25 17:04:25.740: I/logfromc(19039): paramInfo.array=abcdefghi, paramInfo.boolValue=0, paramInfo.charValue=C06-25 17:04:25.740: I/logfromc(19039): paramInfo.doubleValue=3.140000, paramInfo.intValue=2016,  paramInfo.str=Hello from Java06-25 17:04:25.740: I/Hello(19039): log: after setInfo06-25 17:04:25.740: I/logfromc(19039): paramInfo.array=Test array, paramInfo.boolValue=1, paramInfo.charValue=B06-25 17:04:25.740: I/Hello(19039): log: paramInfoGet.boolValue=true paramInfoGet.charValue=B paramInfoGet.doubleValue=2.718206-25 17:04:25.740: I/Hello(19039): log: paramInfoGet.intValue=8 paramInfoGet.array=Test array paramInfoGet.str=Hello from JNI06-25 17:04:25.740: I/Hello(19039): log: finish可以看出,java设置的数值,已经成功传递到C端;而C程序设置的数据,也成功回传到java端了。demo下载:http://download.csdn.net/detail/lintax/9559413

 

转载于:https://www.cnblogs.com/Free-Thinker/p/6831778.html

你可能感兴趣的文章
SQL (FMDB)
查看>>
2012暑期川西旅游之总结
查看>>
Linux发行版的排行
查看>>
宾得镜头大全与发展史
查看>>
spread+wackamole打造全新高可用+负载均衡
查看>>
Xcode 快捷键及代码格式化
查看>>
12010 解密QQ号(队列)
查看>>
Docker简明教程(以安装wget程序为例)
查看>>
2014年辛星完全解读Javascript第一节
查看>>
装配SpringBean(一)--依赖注入
查看>>
daydayup2 codeforces143C
查看>>
ANT打包J2EE项目war包
查看>>
UESTC-我要长高 DP优化
查看>>
java选择文件时提供图像缩略图[转]
查看>>
ubuntu如何安装虚拟机的工具条
查看>>
printf格式输出知识整理
查看>>
sed 命令用法
查看>>
当DIV内出现滚动条,fixed实效怎么办?
查看>>
方维分享系统二次开发, 给评论、主题、回复、活动 加审核的功能
查看>>
Matlab parfor-loop并行运算
查看>>