整理JNI常量函数,用例说明

常量函数非常多,就整理一些常见的函数用例,我先例举常量函数,并做一些标注,最后通过一个实例来一一验证。

常量或参数说明:

  1. env参数是指向函数的列表的指针。在C中调用为(*env)->,在C++中调用为(env)->
  2. 本地方法的obj 的意义取决于该方法是静态还是实例方法(static or an instance method)。当本地方法作为一个实例方法时,第二个参数相当于对象本身,即this. 当本地方法作为一个静态方法时,指向所在类。
  3. java中的String不管是中文还是英文,一个字符总是对应两个字节
  4. Unicode 对应两个字节编码
  5. UTF8对应一个字节编码
  6. 变量的定义
  typedef long            jint;
  typedef _int64         jlong;
  typedef signed char     jbyte;
  typedef unsigned char     jboolean;
  typedef unsigned short    jchar;
  typedef short     jshort;
  typedef float     jfloat;
  typedef double        jdouble;
  typedef jint            jsize;

字符系列常量函数

1、

函数原型:const char* (JNICALL *GetStringUTFChars)(JNIEnv *env, jstring str, jboolean *isCopy)
函数说明:用来取得某个jstring对象相关的Java字符串,把一个Unicode字串转成UTF-8格式字串。 
参数说明:jstring str:传入一个指向java中的String对象的jstring变量,
        jboolean* isCopy:传入一个jboolean的指针,是用来标识是否对java的String对象进行了拷贝。
        如果传入这个jboolean指针不是NULL,则它会给该指针所指向的内存传入JNI_TRUE或JNI_FALSE标识是否进行了拷贝。传入NULL表示不关心是否拷贝字符串,它就不会给jboolean*指向的内存赋值。
        一般会把isCopy设为NULL,不关心Java VM对返回的指针是否直接指向java.lang.String的内容。
        一般不能预知VM是否会拷贝java.lang.String的内容,程序员应该假设GetStringChars会为java.lang.String分配内存。
        在JavaVM的实现中,垃圾回收机制会移动对象,并为对象重新配置内存。一但java.lang.String占用的内存暂时无法被GC重新配置,将产生内存碎片,过多的内存碎片,会更频繁的出现内存不足的假象。
返回类型:char*

2、

函数原型: void (JNICALL *ReleaseStringUTFChars)(JNIEnv *env, jstring str, const char* chars);
函数说明:来释放拷贝的内容
参数说明: jstring str 指定一个jstring变量,即是要释放的本地字符串的来源,
         const char* chars 就是要释放的本地字符串

3、

函数原型:const jchar *(JNICALL *GetStringChars)(JNIEnv *env, jstring str, jboolean *isCopy);
函数说明:用来取得某个jstring对象相关的Java字符串,以Unicode形式存储
参数说明: 参数和GetStringUTFChars函数参数意思一样
返回类型:jchar 两个字节

4、

函数原型:void (JNICALL *ReleaseStringChars)(JNIEnv *env, jstring str, const jchar *chars);
函数说明:同ReleaseStringUTFChars
参数说明: 同ReleaseStringUTFChars
返回类型:void

5、

函数原型:jsize (JNICALL *GetStringLength)(JNIEnv *env, jstring str);
函数说明:获得以Unicode编码的字串长度
参数说明: jstring str Java 传进来的字符串对象
返回类型:Java中String对象中字符的个数

6、

函数原型: jsize (JNICALL *GetStringUTFLength)(JNIEnv *env, jstring str);
函数说明:获得以UTF8编码的字串长度
参数说明: jstring str Java 传进来的字符串对象
返回类型:Java中String对象中字符的个数

7、

函数原型:void GetStringUTFRegion(JNIEnv *env,jstring str, jsize start, jsize len, char *buf)
函数说明:拷贝Java字符串并以UTF-8编码传入buffer。把java字符串的内容直接拷贝到C/C++的字符数组中。
         在呼叫这个函数之前必须有一个C/C++分配出来的字符串,然后传入到这个函数中进行字符串的拷贝(此函数不分配内存)
参数说明:jstring str Java 传进来的字符串对象
        jsize start Java 传进来的字符串对象复制的起始地址
        jsize len 复制的数据长度
        char *buf 存放数据的buf
返回类型:void

8、

函数原型:void GetStringRegion(JNIEnv *env,jstring str, jsize start,jsize len,jchar* buffer);
函数说明:拷贝java字符串并以UTF-16编码传入buffer
函数说明:同GetStringUTFRegion
参数说明: 同GetStringUTFRegion
返回类型:void

9、

函数原型:jstring NewString(JNIEnv *env,const jchar* str,jsize len);
函数说明:在C/C++本地代码中创建JAVA的String字符串对象
参数说明:const jchar* str 在C中创建的jstring对象
        jsize len 组建字符的长度值,从0开始组建
返回类型:jstring 

10、

函数原型:jstring NewStringUTF(const char * str);
函数说明:在C/C++本地代码中创建JAVA的String字符串对象
参数说明:const char* str 在C中创建的jstring对象
          jsize len 组建字符的长度值,从0开始组建
返回类型:jstring

实例验证:

JNIEXPORT jstring JNICALL Java_com_lu_jni_TestCUtils_pramaCallMethodReture
        (JNIEnv * env ,jclass obj,jstring str){


    const jchar* getStr = (*env)->GetStringChars(env,str,JNI_FALSE);
    LOGE("===const jchar* getStrjchar*======getStrData==%s",getStr);
    jsize strSize = (*env)->GetStringLength(env,str);
    LOGE("==jsize strSize===========%d",strSize);
    //void
    (*env)->ReleaseStringChars(env,str,getStr);

    const char *getCStr = (*env)->GetStringUTFChars(env,str,JNI_FALSE);
    LOGE("=const char *getCStr======getCStrData==%s",getCStr);
    jsize strCSize = (*env)->GetStringUTFLength(env,str);
    LOGE("===jsize strCSize======getCStrData==%d",strCSize);
    (*env)->ReleaseStringUTFChars(env,str,getCStr);

    char outBuf [10] ;
    //void
    (*env)->GetStringUTFRegion(env,str,0,5,outBuf);
    LOGE("==char outBuf [10]=======getOutCStrData==%s",outBuf);
    jchar outJBuf[10];
    //void
    (*env)->GetStringRegion(env,str,0,5,outJBuf);
    LOGE("==jchar outJBuf[10]=======getOutCStrData==%s",outJBuf);

    jstring jstr = (*env)->NewString(env,getStr,5);
    LOGE("==jstring jstr=======getStrData==%s",jstr);
    const char * cjstring = "pramaCallMethodReture";
    jstring jstr1 = (*env)->NewStringUTF(env,cjstring);
    LOGE("==const char * cjstring=======getStrData==%s",jstr1);

    return jstr;

}

数组系列常量函数

1、

函数原型:jbyte * (JNICALL *GetByteArrayElements)(JNIEnv *env, jbyteArray array, jboolean *isCopy);
函数说明  将Java中的byte数组转换成JNI中的基本类型,并由该类型的指针指向第一个元素
参数说明:jbyteArray array,Java中的byte数组
        jboolean *isCopy 同字符函数的isCopy
返回类型  jbyte *

2、

函数原型:void (JNICALL *ReleaseByteArrayElements)(JNIEnv *env, jbyteArray array, jbyte *elems, jint mode)
函数说明:释放分配的jbyte数组
参数说明:jbyteArray array  Java中的byte数组
        jbyte *elems 由GetByteArrayElements函数分配的空间
        jint mode 释放模式 一般给0

3、

函数原型:jsize (JNICALL *GetArrayLength)(JNIEnv *env, jarray array);
函数说明:获得数组元素的个数
参数说明:jarray array  Java数组的对象
返回类型: jsize 数组元素个数

4、

函数原型:void (JNICALL *GetByteArrayRegion)(JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf);
函数说明:将jbyteArray数组拷贝到buf中
参数说明:jbyteArray array 生成的jbyteArray 数组,可以使Java传递的,也可以使jni中自己生成
         jsize start  jbyteArray数组的起始地址
         jsize 要拷贝的数据长度
         jbyte buf 待存放数据的 jbyte buf
返回类型  void 

5、

函数原型:void (JNICALL *SetByteArrayRegion)(JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf);
函数说明:将 buf数组中的值拷贝到jbyteArray数组中
参数说明:jbyteArray array 生成的jbyteArray 数组,可以使Java传递的,也可以使jni中自己生成
        jsize start  jbyteArray数组的起始地址, 从buf的首地址开始复制
        jsize 要拷贝的数据长度 
        jbyte buf 待存放数据的 jbyte buf
返回类型  void 

6、

函数原型:jbyteArray (JNICALL *NewByteArray)(JNIEnv *env, jsize len);
函数说明:生成一个jbyteArray型数组(一维数组)
参数说明:jsize len 生成数组的大小
返回类型:jbyteArray 数组

7、还有其它类型生成的一维数组

  1. jbooleanArray (JNICALL *NewBooleanArray)(JNIEnv *env, jsize len);
  2. jbyteArray (JNICALL *NewByteArray)(JNIEnv *env, jsize
  3. jcharArray (JNICALL *NewCharArray)(JNIEnv *env, jsize len);
  4. jshortArray (JNICALL *NewShortArray)(JNIEnv *env, jsize len);
  5. jintArray (JNICALL *NewIntArray)(JNIEnv *env, jsize len);
  6. jlongArray (JNICALL *NewLongArray)(JNIEnv *env, jsize len);
  7. jfloatArray (JNICALL *NewFloatArray)(JNIEnv *env, jsize len);
  8. jdoubleArray (JNICALL *NewDoubleArray)(JNIEnv *env, jsize len);
  9. jobjectArray (JNICALL *NewObjectArray)(JNIEnv *env, jsize len, jclass clazz, jobject init);

实体验证:

JNIEXPORT jstring JNICALL Java_com_lu_jni_TestCUtils_testArray
        (JNIEnv * env, jobject obj, jbyteArray bdata){

    jint i = 0 ;
    //将Java中的byte数组转换成JNI中的基本类型,并由该类型的指针指向第一个元素
    jbyte *jByte = (*env)->GetByteArrayElements(env,bdata,NULL);

    //获得数组元素的个数
    jsize len = (*env)->GetArrayLength(env,bdata);
    LOGE("arrary len = %d",len);

    /*
     * JNI 程序开发者要遵循 native 语言本身的内存管理机制,避免造成内存泄漏。
     * 以 C 语言为例,当用 malloc() 在进程堆中动态分配内存时,JNI 程序在使用完后,应当调用 free() 将内存释放。
     */

    /*
     * malloc函数是一种分配长度为num_bytes字节的内存块的函数,可以向系统申请分配指定size个字节的内存空间。
     * malloc的全称是memory allocation,中文叫动态内存分配,当无法知道内存具体位置的时候,
     * 想要绑定真正的内存空间,就需要用到动态的分配内存。
     */

    //unsigned无符号型 字符数组
    //类型名称        字节数   取值范围
    //unsigned char     1        0~255
    unsigned char *cBuf  = (unsigned char *)malloc(len);

    /*memset()函数原型是extern void *memset(void *buffer, int c, int count)
     *      buffer:为指针或是数组,
     *      c:是赋给buffer的值,
     *      count:是buffer的长度.
     */

    /*
     * 作用:
     * 这个函数在socket中多用于清空数组.如:原型是memset(buffer, 0, sizeof(buffer))
     * Memset 用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为‘ ’或‘/0’;
     * 例:char a[100];memset(a, '/0', sizeof(a));
     * memset可以方便的清空一个结构类型的变量或数组。
     */

    //memset() 函数常用于内存空间初始化。
    memset(cBuf,0,len);
    //memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度。
    memcpy(cBuf,jByte,len);

    jbyte *buf = (jbyte * )malloc(len);
    //另外一种方法 将bdata数组拷贝到buf中
    (*env)->GetByteArrayRegion(env,bdata,0,len,buf);

    //生成一个jbyteArray型数组(一维数组)
    jbyteArray byteBuf = (*env)->NewByteArray(env,len);

    //将 buf数组中的值拷贝到jbyteArray数组中
    //(*env)->SetByteArrayRegion(env,byteBuf,0,len,buf);
    (*env)->SetByteArrayRegion(env,byteBuf,2,len-5,buf);//从第二开始取值(包括第二个)往后取4个,其他的补0
    //将Java中的byte数组转换成JNI中的基本类型,并由该类型的指针指向第一个元素
    jByte = (*env)->GetByteArrayElements(env,byteBuf,NULL);

    for(i = 0 ; i < len; i++)
    {
        LOGE("=======%d",jByte[i]);
    }

    (*env)->ReleaseByteArrayElements(env, bdata, jByte, 0);

    const char * cjstring = "test array success !";
    jstring jstr = (*env)->NewStringUTF(env,cjstring);
    return jstr;


}
 
 还有和jbyteArray一样的其它类型的数组,用法一致
 
  jbooleanArray
  jbyteArray
  jcharArray
  jshortArray
  jintArray
  jlongArray
  jfloatArray
  jdoubleArray
  jobjectArray

在jni中调用Java中的方法的函数

类型签名:

签名是一种用参数个数和类型区分同名方法的手段,即解决方法重载问题。
其中要特别注意的是:

  1. 类描述符开头的'L'与结尾的';'必须要有 String类型的签名是“Ljava/lang/String;”
  2. 数组描述符,开头的'['必须有.
  3. 方法描述符规则:" (各参数描述符)返回值描述符",其中参数描述符间没有任何分隔
    符号
类型签名  Java类型      C类型
    V      void            void
    Z      jboolean     boolean
    I      jint              int
    J      jlong            long
    D      jdouble       double
    F      jfloat            float
    B      jbyte            byte
    C      jchar           char
    S      jshort          short
          数组则以"["开始,用两个字符表示
    [I       jintArray      int[]
    [F     jfloatArray    float[]
    [B     jbyteArray    byte[]
    [C    jcharArray    char[]
    [S    jshortArray   short[]
    [D    jdoubleArray double[]
    [J     jlongArray     long[]
    [Z    jbooleanArray boolean[]

1、

函数原型:jclass (JNICALL *GetObjectClass)(JNIEnv *env, jobject obj);
函数说明:函数得到该对像的类,该函数返回一个jclass类型值,其中obj参数表示要你想要得到类型的类对象。通过该方法可以获取到调用该方法的对象所在的类
参数说明:见开头
返回类型:jclass

2、

函数原型:jclass (JNICALL *FindClass)(JNIEnv *env, const char *name);
函数说明:功能同GetObjectClass,但是在访问静态域的时候必须使用FindClass,而不能使用GetObjectClass。
         在FindClass()的第二个参数是类的编码签名,类的编码签名和 基本类型的编码签名有所不同,
         如果类在当前包中,就直接是类的名称,如果类不在当前包中则要加入该类的详细路径:
         例如String类在java.lang 包中,则String的签名要写成( Ljava/lang/String;),
         其中的(L和;)是不可少的,其中(;)是表达是的终止符
参数说明:const char *name:类全名(即包名后跟类名,之间由“/”分隔)。如果该名称以“[”(数组签名字符)打头,则返回一个一维数组类。
返回类型:jclass

3、

 函数原型:jfieldID (JNICALL *GetFieldID)(JNIEnv *env, jclass clazz, const char *name, const char *sig);
 函数说明:获取实例域的ID
 参数说明:const char *name Java中定义的实例域的名称
          const char *sig  实例域的类型签名
          jclass clazz 获取到的类
 返回类型:jfieldID

4、

 函数原型:jobject (JNICALL *GetObjectField)(JNIEnv *env, jobject obj, jfieldID fieldID);
 函数说明:获取到域ID的内容,Java的String类型,要用GetObjectField函数获取,这里提示大家没有
          GetStringField这样的函数在JNI中,或者说在C语言中
 参数说明:jfieldID fieldID 有效的域ID
          jobject obj  Java中传下来的类对象
 返回类型:域内容

5、

函数原型:jint (JNICALL *GetIntField)(JNIEnv *env, jobject obj, jfieldID fieldID);
函数说明:获取整型实例域的内容
参数说明:jfieldID fieldID 有效的域ID
          jobject obj  Java中传下来的类对象
返回类型:jint

6、

还有其它类型的获取实例域的内容函数用法和GetIntField方法使用一样,
 1. jboolean (JNICALL *GetBooleanField)(JNIEnv *env, jobject obj, jfieldID fieldID);
 2. jbyte (JNICALL *GetByteField)(JNIEnv *env, jobject obj, jfieldID fieldID);
 3. jchar (JNICALL *GetCharField)(JNIEnv *env, jobject obj, jfieldID fieldID);
 4. jshort (JNICALL *GetShortField)JNIEnv *env, jobject obj, jfieldID fieldID);
 5. jlong (JNICALL *GetLongField)(JNIEnv *env, jobject obj, jfieldID fieldID);
 6. jfloat (JNICALL *GetFloatField)(JNIEnv *env, jobject obj, jfieldID fieldID);
 7. jdouble (JNICALL *GetDoubleField)(JNIEnv *env, jobject obj, jfieldID fieldID);

7、

函数原型:jfieldID (JNICALL *GetStaticFieldID)(JNIEnv *env, jclass clazz, const char *name, const char *sig);
函数说明:获取静态域ID
参数说明:同GetFieldID
返回类型:jfieldID

8、

函数原型:jbyte (JNICALL *GetStaticByteField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
函数说明:获取静态域的数值
参数说明:jclass clazz FindClass函数获取到的Class,注意: 不是obj
           fieldID fieldID 同GetIntField
返回类型:jbyte

9、

还有其它类型获取静态实例域的函数,使用方法同GetStaticByteField

1. jobject (JNICALL *GetStaticObjectField)(JNIEnv *env, jclass clazz, jfieldID fieldID); //jstring
2. jboolean (JNICALL *GetStaticBooleanField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
3. jchar (JNICALL *GetStaticCharField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
4. jshort (JNICALL *GetStaticShortField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
5. jint (JNICALL *GetStaticIntField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
6. jlong (JNICALL *GetStaticLongField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
7. jfloat (JNICALL *GetStaticFloatField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
8. jdouble (JNICALL *GetStaticDoubleField)(JNIEnv *env, jclass clazz, jfieldID fieldID);

10、

函数原型:void (JNICALL *SetObjectField)(JNIEnv *env, jobject obj, jfieldID fieldID, jobject val);   
函数说明:设置fieldID对应获取的实例域的新值(非静态),此函数针对jstring
参数说明:jfieldID fieldID,有效的域ID
           jobject val ,域的新值
返回类型:void

11、

函数原型:void (JNICALL *SetByteField)(JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val);  
函数说明:设置字节型的实例域(非静态)
参数说明:同SetObjectField
返回类型:void 

12、

还有其它类型的设置实例域的方法使用方法和SetByteField一样
1. void (JNICALL *SetBooleanField)(JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val);
2. void (JNICALL *SetCharField)(JNIEnv *env, jobject obj, jfieldID fieldID, jchar val);
3. void (JNICALL *SetShortField)(JNIEnv *env, jobject obj, jfieldID fieldID, jshort val);
4. void (JNICALL *SetIntField)(JNIEnv *env, jobject obj, jfieldID fieldID, jint val);
5. void (JNICALL *SetLongField)(JNIEnv *env, jobject obj, jfieldID fieldID, jlong val);
6. void (JNICALL *SetFloatField)(JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val);
7. void (JNICALL *SetDoubleField)(JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val);

13、

函数原型:void (JNICALL *SetStaticByteField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value);
函数说明:设置fieldID对应获取的实例域的新值(静态)
参数说明:jclass clazz,FindClass获取到的cla
返回类型:void

14、

还有其它类型的设置静态实例域的方法使用方法和SetStaticByteField一样
1. void (JNICALL *SetStaticObjectField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value);
2. void (JNICALL *SetStaticBooleanField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value);
3. void (JNICALL *SetStaticCharField) (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value);
4. void (JNICALL *SetStaticShortField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value);
5. void (JNICALL *SetStaticIntField) (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value);
6. void (JNICALL *SetStaticLongField)   (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value);
7. void (JNICALL *SetStaticFloatField)  (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value);
8. void (JNICALL *SetStaticDoubleField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value);

以上方法使用的实例如下:

JNIEXPORT jstring JNICALL Java_com_lu_jni_TestCUtils_noPramaCallMethodReture
        (JNIEnv * env , jobject objs){

    jclass cls = (*env)->FindClass(env,"com/lu/jni/CommonUtil");
//    //"()Ljava/lang/String;" 表示参数为空 返回值是String类型   ()V  无参 无返回
    jmethodID method = (*env)->GetMethodID(env,cls,"callJavaRetureString","()Ljava/lang/String;");
    jobject jobj = (*env)->AllocObject(env,cls);
    jstring msg = (jstring)(*env)->CallObjectMethod(env,jobj,method);


    const char * cjstring = "new String";
    jstring jstr = (*env)->NewStringUTF(env,cjstring);
    //找到对应类
    jclass cls1 = (*env)->FindClass(env,"com/lu/jni/TestCUtils");
    //创建实例
    jobject obj = (*env)->AllocObject(env,cls1);

    //获取实例域String
    jfieldID mfieldid = (*env)->GetFieldID(env,cls1,"data","Ljava/lang/String;");
 (*env)->SetObjectField(env,obj,mfieldid,jstr);
    jstring getfieldValue = (jstring)(*env)->GetObjectField(env,obj,mfieldid);
    const char *display = (*env)->GetStringUTFChars(env,getfieldValue,NULL);
    LOGE("GET CLASS STRING FIELD VALUE  == %s",display);
    //获取实例域INT
    mfieldid = (*env)->GetFieldID(env,cls1,"mInt","I");
    jint getInt = (*env)->GetIntField(env,obj,mfieldid);
    LOGE("GET CLASS INT FIELD VALUE == %d",getInt);

    //获取byte实例域
    jbyte mbyte = 45;
    mfieldid = (*env)->GetFieldID(env,cls1,"mByte","B");
    (*env)->SetByteField(env,obj,mfieldid,mbyte);
    jbyte getByte = (*env)->GetByteField(env,obj,mfieldid);
    LOGE("GET CLASS BYTE FIELD VALUE == %d",getByte);

    //获取静态的byte实例域 必须使用findclass函数
    mfieldid = (*env)->GetStaticFieldID(env,cls1,"staByte","B");
    (*env)->SetStaticByteField(env,cls1,mfieldid,(jbyte)65);
    jbyte getStaByte = (*env)->GetStaticByteField(env,cls1,mfieldid);
    LOGE("GET CLASS STATIC BYTE FIELD VALUE == %d",getStaByte);

    (*env)->ReleaseStringUTFChars(env,getfieldValue,display);

    return msg;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。