android jni jobjectArray存储输出不同类型的数据

android jni jobjectArray存储输出不同类型的数据

1.jni的定义

 JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++)。从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他编程语言,只要调用约定受支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的。例如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少要保证本地代码能工作在任何Java 虚拟机环境。

2.android中为什么使用jni

 我的理解是:
 1.代码保护性提高,c++编译成的动态库不易被反编译。
 2.补充java的性能,很多优秀的开源库使用c/c++,在性能上c/c++更快。

3.android使用jni弊端

1.程序的稳定性变弱,native日志不易跟踪和解决,需要扎实的c++编写,java c++ 之间数据结构转换需要小心,程序整体接口封装稍显冗余。

4.android使用jni,java 与c++数据结构转换

1.基本数据类型

这里写图片描述

2.引用数据类型

这里写图片描述

3.jobjectArray如何存储任何类型数据

 这里重点讲一下 jobjectArray如何存储各种数据类型。jni有自己的一套数据转换规则,如果是基本数据类型,或者某一类的数据类,很好处理,每种都有对应的方式,但是如果是多种数据结构,存储到jni里面,就会稍显麻烦,这点在单纯的java  c++却不存在,直接用顶级 object类就可以,但是jni里面却是编译不过。代码中类或者字段赋值用 XXX YYY VVV MMM 等表示。
JNIEXPORT jobjectArray JNICALL Java_com_xxx_xxx_xxx_jni_1GetAllObject
(JNIEnv *env, jclass , jlong instance )
{
        XXX*xxx= (XXX*) instance;

        MyArray<VVV> arrVar;

        YYY  yyy;
        ((XXX*)xxx)->GetXXXs(yyy);
        jint nSize = arrVar.GetSize();
        // 获取类对象
        jclass cls = env->FindClass("java/lang/Object");
        jobjectArray mjobjectArray = (jobjectArray)env->NewObjectArray(nSize, cls, NULL);
        jint nIndex = 0;
        for (jint i = 0; i < nSize; i++)
        {   
                switch(arrVar[i].GetType())
                {

                case VVV::Boolean:
                    {

                        jboolean myjboolean=MMM;
                        const char *mychar;
                        if(myjboolean){
                            mychar="true";
                        }else{
                            mychar="false";
                        }
                        jstring mystring=env->NewStringUTF(mychar);
                        env->SetObjectArrayElement(mjobjectArray, 
                        nIndex,(jobject)mystring);
                        nIndex++;
                    }
                    break;
                case VVV::Short:
                    {

                        jshort myjshort=MMM;
                        char buf[64];
                        sprintf(buf,"%d",myjshort);
                        jstring mystring=env->NewStringUTF(buf);
                        env->SetObjectArrayElement(mjobjectArray,
                        nIndex,(jobject)mystring);
                        nIndex++;
                    }
                    break;
                case VVV::Integer:
                    {

                        jint myjint=MMM;
                        char buf[64];
                        sprintf(buf,"%d",myjint);
                        jstring mystring=env->NewStringUTF(buf);
                        env->SetObjectArrayElement(mjobjectArray, 
                        nIndex,(jobject)mystring);
                        nIndex++;
                    }
                    break;
                case VVV::Long:
                    {

                        jlong myjlong=MMM;
                        char buf[64];
                        sprintf(buf,"%d",myjlong);
                        jstring mystring=env->NewStringUTF(buf);
                        env->SetObjectArrayElement(mjobjectArray, 
                        nIndex,(jobject)mystring);
                        nIndex++;
                    }
                    break;
                case VVV::Float:
                    {

                        jfloat myfloat=MMM;
                        char buf[128];
                        sprintf(buf,"%f",myfloat);
                        jstring mystring=env->NewStringUTF(buf);
                        env->SetObjectArrayElement(mjobjectArray, 
                        nIndex,(jobject)mystring);
                        nIndex++;
                    }
                    break;
                case VVV::Double:
                    {   
                        jdouble myjdouble=MMM;
                        char buf[128];
                        sprintf(buf,"%f",myjdouble);
                        jstring mystring=env->NewStringUTF(buf);
                        env->SetObjectArrayElement(mjobjectArray, 
                        nIndex,(jobject)mystring);
                        nIndex++;
                    }
                    break;
                case VVV::Date:
                case VVV::Time:
                case VVV::TimeStamp:
                    {
                        jniString str =MMM;
                        env->SetObjectArrayElement(mjobjectArray,
                         nIndex, (jobject)str);
                        nIndex++;
                    }
                    break;
                case VVV::String:
                    {
                        jniString str = arrVar[i].ToString();
                        env->SetObjectArrayElement(mjobjectArray, 
                        nIndex, (jobject)str);
                        nIndex++;
                    }
                    break;

                default:
                    // 以上类型都不满足,返回nullptr;
                    const char *mychar="NULL";
                    jstring mystring=env->NewStringUTF(mychar);
                    env->SetObjectArrayElement(mjobjectArray,
                     nIndex, (jobject)mystring);
                    nIndex++;
                    //delete mychar;
                    break;
                }
            }
        }
        return mjobjectArray;
}
  以上就是 各种数据结构转换为objectArray输出的例子,核心思想是在填充数据元素的时候需要注意:env>SetObjectArrayElement(mjobjectArray, nIndex, (jobject)mystring);  所以必须将第三个变量转换为jstring  然后向上转型为 jobject类型,有人会说  草,既然是jobject,我为毛只能转为jstring才能向上转型呢? 这点在其实和 java c++处理上真好不一样。请看下图

这里写图片描述

      图中很明白 jstring基类 是 jobject ,而基本数据类型 jint  jboolean jlong等基类不是jobect,所以编译会出错,需要都格式化成字符串一起存储在 jobjectArray里面。

3.jobjectArray 总结

     有人会问,为什么非得存进一个里面,单独输出不可以吗? 每种都有对应的array。 当然这样是可以的,但是上层的话需要开很多组件接口,另外效率上面差距非常大。   项目中使用 查询实体各种数据类型的一些属性,  之前单独的存储 和jobjectArray的存储差距是非常大的,大概size 200左右的时候,提升了150-200倍的时间效率。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值