zoukankan      html  css  js  c++  java
  • JNI 参数传递

    对于基本数据类型,在native层接口看到的参数,对应的都已经转换成native层的数据类型了,只是名字为了好对应,用 typedef 做了转换。
     
     
    JAVA 的基本数据类型:
    数据类型                大小               范围                                                 默认值 
    
    byte(字节) 8    -128 - 127 0
    shot(短整型) 16   -32768 - 32768 0
    int(整型) 32   -2147483648-2147483648 0
    long(长整型) 64   -9233372036854477808-9233372036854477808 0
    float(浮点型) 32   -3.40292347E+38-3.40292347E+38 0.0f
    double(双精度) 64   -1.79769313486231570E+308-1.79769313486231570E+308 0.0d
    char(字符型) 16 ‘ \u0000 - u\ffff ’     ‘\u0000 ’
    boolean(布尔型) 1 true/false     false
     
    JAVA 数据类型对应的JNI数据类型:
     
    /* "cardinal indices and sizes" */
    #ifdef HAVE_INTTYPES_H
    # include <inttypes.h>      /* C99 */
    typedef uint8_t              jboolean;       /* unsigned 8 bits */
    typedef int8_t                jbyte;          /* signed 8 bits */
    typedef uint16_t             jchar;          /* unsigned 16 bits */
    typedef int16_t             jshort;          /* signed 16 bits */
    typedef int32_t             jint;              /* signed 32 bits */
    typedef int64_t             jlong;           /* signed 64 bits */
    typedef float                 jfloat;           /* 32-bit IEEE 754 */
    typedef double              jdouble;        /* 64-bit IEEE 754 */
    #else
    typedef unsigned char       jboolean;       /* unsigned 8 bits */
    typedef signed char         jbyte;          /* signed 8 bits */
    typedef unsigned short    jchar;          /* unsigned 16 bits */
    typedef short               jshort;         /* signed 16 bits */
    typedef int                 jint;           /* signed 32 bits */
    typedef long long         jlong;          /* signed 64 bits */
    typedef float               jfloat;         /* 32-bit IEEE 754 */
    typedef double            jdouble;        /* 64-bit IEEE 754 */
     
    typedef jint              jsize;
     
     
    Java的 String 和 JNI中的 JString 的关系:
    #ifdef __cplusplus
    /*
     * Reference types, in C++
     */
    class _jobject {};
    class _jstring : public _jobject {};
    typedef _jobject*       jobject;
    typedef _jstring*       jstring;
    #else 
    /* not __cplusplus */
    typedef void*           jobject;
    typedef jobject         jstring;
    #endif 
    比如java中的方法:
    public native int test(String str, int i, long l, short s, double d, float f, char c);
    用 javah 变成 jni的方法后成这样:
    JNIEXPORT jint JNICALL Java_com_jni_test_EncodeJNI_test (JNIEnv *env, jobject objThis, jstring str, jint i, jlong l, jshort s, jdouble d, jfloat f, jchar c);
     
    jlong 在 C 里面对应的 long long 类型,有64bit,输出时用 "%lld"

    数组的传递:

    public native String arrayTest(String[] strArray, int[] iArray, long[] lArray, short[] sArray, double[] dArray, float[] fArray, char[] cArray);

    JNIEXPORT jstring JNICALL Java_com_jni_test_EncodeJNI_arrayTest(JNIEnv *env, jobject objThis, jobjectArray strArray, jintArray iArray, jlongArray lArray, jshortArray sArray, jdoubleArray dArray, jfloatArray fArray, jcharArray cArray);

        jbooleanArray (*NewBooleanArray)(JNIEnv*, jsize);
        jbyteArray    (*NewByteArray)(JNIEnv*, jsize);
        jcharArray    (*NewCharArray)(JNIEnv*, jsize);
        jshortArray   (*NewShortArray)(JNIEnv*, jsize);
        jintArray     (*NewIntArray)(JNIEnv*, jsize);
        jlongArray    (*NewLongArray)(JNIEnv*, jsize);
        jfloatArray   (*NewFloatArray)(JNIEnv*, jsize);
        jdoubleArray  (*NewDoubleArray)(JNIEnv*, jsize);
    
        jboolean*   (*GetBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*);
        jbyte*      (*GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*);
        jchar*      (*GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*);
        jshort*     (*GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*);
        jint*       (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);
        jlong*      (*GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*);
        jfloat*     (*GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*);
        jdouble*    (*GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*);

     获取数组长度:     jsize   (*GetArrayLength)(JNIEnv*, jarray);

    设置IntArray 的值
    void SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize len, const jint* buf)

    View Code
    #include "com_TestCopyPix_jni.h"
    //#include other headers
    JNIEXPORT jintArray JNICALL Java_com_TestCopyPix_jni_ct(JNIEnv *env, jobject obj) {
        //jdoubleArray inner = (*env)->NewDoubleArray(env, 3);
    //    int i = 1;
    //    jintArray  array;//定义数组对象
    //    array = (*env)-> NewIntArray(env, 10);
    //    for(; i<= 10; i++)
    //      (*env)->SetIntArrayRegion(env, array, i-1, 1, &i);
    //    /* 获取数组对象的元素个数 */
    //    int len = (*env)->GetArrayLength(env, array);
    //    /* 获取数组中的所有元素 */
    //    jint* elems = (*env)-> GetIntArrayElements(env, array, 0);
    //    for(i=0; i<len; i++)
    //            printf("ELEMENT %d IS %d\n", i, elems[i]);
    
    
        int i = 1;
        int a = 20;
        int b = 200;
        jintArray  array;//定义数组对象
        array = (*env)-> NewIntArray(env, 2);
        (*env)->SetIntArrayRegion(env, array, 0, 1, &a);
        (*env)->SetIntArrayRegion(env, array, 1, 1, &b);
    
    //        for(; i<= 2; i++)
    //          (*env)->SetIntArrayRegion(env, array, i-1, 1, &i);
            /* 获取数组对象的元素个数 */
    //        int len = (*env)->GetArrayLength(env, array);
    //        /* 获取数组中的所有元素 */
    //        jint* elems = (*env)-> GetIntArrayElements(env, array, 0);
    
    
        return array;
    
    }
    View Code
    jintArray
    Java_com_summer_PointerTestActivity_test( JNIEnv* env,
                                                      jobject thiz,jintArray nums)
    {
        //获取传入数组的长度
        jsize len = (*env)->GetArrayLength(env, nums);
        //在java中申请一块内存  以用来将C的数组传输给java程序
        jintArray ret=(*env)->NewIntArray(env,len);
    
        //获取传入的数组
        jint *body = (*env)->GetIntArrayElements(env, nums, 0);
        int i;
        for(i=0;i<len;i++)
        {
            body[i] *=2;
        }
    
        //将C的数组拷贝给java中的数组
        (*env)->SetIntArrayRegion(env,ret,0,len,body);
        return ret;
    }
    String的处理
    Java String不能直接被C++程序使用,需要先用 env->GetStringUTFChars把它转化为UTF编码形式的char*再进行处理。
    如:
    jboolean isCopy = 0;
    str = env->GetStringUTFChars(prompt, &isCopy);   //C 中是 (*env)->GetStringUTFChars(env,  str, &isCopy);  这里返回的char*有字符串结束符
     
    如果想返回一个java的String类型的话,我们可以通过env->NewStringUTF命令用一个char*来创建一个jstring,然后让该jstring返回就可以。
    如:jstring rtstr = env->NewStringUTF(tmpstr);
    上面的GetStringUTFChars,ReleaseStringUTFChars,NewStringUTF都是JNI提供的处理String类型的函数,更多的JNI函数请查看jin.h。
     
    注意在使用完你所转换之后的对象之后,需要显示调用 ReleaseStringUTFChars(JNIEnv*, jstring, const char*)方法,让JVM释放转换成UTF-8的string的对象的空间,如果不显示的调用的话,JVM中会一直保存 该对象,不会被垃圾回收器回收,因此就会导致内存溢出。
     
      下面是访问String的一些方法, C中:
      ◆const   char*GetStringUTFChars(JNIEnv*, jstring, jboolean*);  将jstring转换成为UTF-8格式的char*
      ◆const   jchar* GetStringChars(JNIEnv*, jstring, jboolean*);      将jstring转换成为Unicode格式的char*
      ◆ void    ReleaseStringUTFChars(JNIEnv*, jstring, const char*);  释放指向UTF-8格式的char*的指针
      ◆void     ReleaseStringChars(JNIEnv*, jstring, const jchar*);       释放指向Unicode格式的char*的指针
      ◆jstring  NewStringUTF)JNIEnv*, const char*);                          创建一个UTF-8格式的String对象
      ◆jstring  NewString(JNIEnv*, const jchar*, jsize);                      创建一个Unicode格式的String对象
      ◆jsize     GetStringUTFLength)(JNIEnv*, jstring);                       获取 UTF-8格式的char*的长度 
      ◆jsize     GetStringLength)(JNIEnv*, jstring);                            获取Unicode格式的char*的长 度
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    利用角色简化playbook
    lamp
    playbook部署lamp
    ansible-playbook配置不同系统yum源
    66. 加一
    628. 三个数的最大乘积
    977. 有序数组的平方
    383. 赎金信
    203. 移除链表元素
    83. 删除排序链表中的重复元素
  • 原文地址:https://www.cnblogs.com/zijianlu/p/2749390.html
Copyright © 2011-2022 走看看