Android NDK development] [JNI analytical method (string array parameter passed | string traversal | type strong turn | Java and C strings to convert a string | string release)



I. C / C ++ type in the Java array of strings



JNI in C / C ++ code to Java array type String: jobjectArray ;

① Status JNI type: not defined types in Java JNI array of strings, the only defines Java string type jstring;

② Object corresponding to jobject: jobject Java Object type corresponding to the type in the C / C ++ environment, Java string is of type Object;

③ type string array: Thus using an array of objects jobjectArray in C / C ++ environment within a string array type;



II. Get string array length



1 Prerequisites: Java layer pass parameters jobjectArray stringArray, this parameter is Java code String [] stringArray parameter;

stringArray parameters GetArrayLength following method is jobjectArray type;


2. Get the length of the string array Code Example: wherein the value returned is of type int jsize alias;

jsize stringArrayLength = env->GetArrayLength(stringArray);

GetArrayLength method detailed analysis following reference:
GetArrayLength analytical method (Get jarray array length)



III. Get string array elements



C / C ++ code specified index acquired Java string array type element;


1. method call: call JNIEnv * env of GetObjectArrayElement methods for obtaining a specified index jobject reference type variable;


. Prototype Method 2:

struct _JNIEnv {
    /* _JNIEnv  结构体中封装了 JNINativeInterface 结构体指针 */
    const struct JNINativeInterface* functions;
    ...
    // 最终 调用的 还是 JNINativeInterface 结构体中封装的 GetObjectArrayElement方法
    jobject GetObjectArrayElement(jobjectArray array, jsize index)
    { return functions->GetObjectArrayElement(this, array, index); }
    ...
}

. 3 GetObjectArrayElement parameters:

① jobjectArray array parameters: passed by the Java layer Java array of objects;

② jsize index parameters: the index value of the array element to be acquired;


4. Get the specified code sample object array element:

Wherein the parameter is jobjectArray stringArray type, passed by the JNI method;

Wherein the parameter i is of type int, is the index value to get the element, counting from 0;

jobject string_object = env->GetObjectArrayElement(stringArray, i);


. IV type strong rotation (jobject -> jstring)



The jobject into jstring type: string_object jobject type is variable;

        // 2.2 将 jobject 类型强转成 jstring 类型 , 这两个都代表了 Java 的数据类型
        jstring string_java = static_cast<jstring>(string_object);

Reference to the following detailed blog:
[] Type C ++ language conversion (operator | const_cast | static_cast | dynamic_cast | reinterpret_cast | string conversion)



. V string conversion (jstring -> char *)



. 1 ReleaseStringUTFChars Method: The jstring type string (in Java) into char * (string C / C ++ in) type string;


2. The function prototype: the jstring String parameter is passed through JNI Java, Java string Representative;

struct _JNIEnv {
    /* _JNIEnv  结构体中封装了 JNINativeInterface 结构体指针 */
    const struct JNINativeInterface* functions;
    ...
    // 最终 调用的 还是 JNINativeInterface 结构体中封装的 GetStringUTFChars 方法
    const char* GetStringUTFChars(jstring string, jboolean* isCopy)
    { return functions->GetStringUTFChars(this, string, isCopy); }
    ...
}

. 3 jboolean * isCopy parameter: This parameter is used to specify the type jintArray variable into a variable of type pointer jint *, to generate a new pointer variable manner;


① the parameter pointer is set to point JNI_TRUE: the int array data copied to a new memory space, and returns the address of the first memory space;

② the parameter pointer is set to point JNI_FALSE: direct use of the array address of the java int, int return the first address in the array java;

③ The parameter to NULL (recommended): indicates do not care about how to automatically generate mode selection pointer, which generates a do not care in general embodiment;

④ jboolean Type Value: jboolean values 0 and 1 only, and may be used JNI_FALSE JNI_TRUE macros;

#define JNI_FALSE 0
#define JNI_TRUE 1

. 4 jstring string into a char * string example:

const char *string_c = env->GetStringUTFChars(string_java, JNI_FALSE);


VI. String release



. 1 ReleaseStringUTFChars Method: The Java string and C / C ++ strings are released;


2. Prototype:

jstring string parameter is passed in Java through JNI, Java string behalf;

const char * utf GetStringUTFChars parameters by the above method is converted into a string Java C / C ++ string;

struct _JNIEnv {
    /* _JNIEnv  结构体中封装了 JNINativeInterface 结构体指针 */
    const struct JNINativeInterface* functions;
    ...
    // 最终 调用的 还是 JNINativeInterface 结构体中封装的 ReleaseStringUTFChars 方法
    void ReleaseStringUTFChars(jstring string, const char* utf)
    { functions->ReleaseStringUTFChars(this, string, utf); }
    ...
}



VII. The sample code portion



Part Code Example:

#include <jni.h>
#include <string>

//导入日志库
#include <android/log.h>

//定义日志宏 , 其中的 __VA_ARGS__ 表示可变参数
#define  LOGE(...) __android_log_print(ANDROID_LOG_ERROR,"JNI",__VA_ARGS__);

...


extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_jni_MainActivity_jniArrayTest(JNIEnv *env, jobject instance, jintArray intArray_,
                                           jobjectArray stringArray) {

    
    ...


    // II . 引用类型数组操作 ( 获取字符串数组 )

    // 1 . 获取字符串数组长度
    jsize stringArrayLength = env->GetArrayLength(stringArray);

    // 2 . 遍历字符串数组
    for(int i = 0; i < stringArrayLength; i ++) {

        /*
            2.1 获取 jobject 数组中第 i 个元素
                注意 : 获取的是 jobject 类型变量

            函数原型 : jobject GetObjectArrayElement(jobjectArray array, jsize index)

                jobjectArray array 参数 : 是 Java 层传入的 Java 对象数组 参数 , 即 Native 层的调用函数的参数
                jsize index 参数 : 对象元素的索引值 , 取值范围 0 ~ stringArrayLength - 1

                返回值 : 返回的是 jobject 类型的变量
         */
        jobject string_object = env->GetObjectArrayElement(stringArray, i);

        // 2.2 将 jobject 类型强转成 jstring 类型 , 这两个都代表了 Java 的数据类型
        jstring string_java = static_cast<jstring>(string_object);

        /*
            2.3 将 jstring 类型转为 char* 类型

            jstring 类型简介 :
                class _jobject {};
                class _jstring : public _jobject {};
                typedef _jstring*       jstring;

                由上面可见 , jstring 只是 继承了 _jobject 类 , 没有任何实现 , 是一个空类
                因此需要借助 C/C++ 方法 将 java 类型的 jstring 字符串 其转为 C/C++ 类型的 char* 类型字符串

            转换函数原型 : void ReleaseStringUTFChars(jstring string, const char* utf)
         */
        const char *string_c = env->GetStringUTFChars(string_java, 0);

        // 2.4 打印 转换后的 字符串值
        __android_log_print(ANDROID_LOG_INFO, "JNI_TAG", "打印字符串数组元素 : %d . %s", i, string_c);


        // 2.5 释放 char* 字符串
        env->ReleaseStringUTFChars(string_java, string_c);

    }

}

Code execution results:

01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印 int 数组元素 : 0 . 1
01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印 int 数组元素 : 1 . 2
01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印 int 数组元素 : 2 . 666
01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印 int 数组元素 : 3 . 888
01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印 int 数组元素 : 4 . 95555
01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印字符串数组元素 : 0 . Hello
01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印字符串数组元素 : 1 . World
01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: 打印字符串数组元素 : 2 . Hanshuliang
01-12 19:45:59.634 11885-11885/kim.hsl.jni I/JNI_TAG: Java 层 jniArrayTest 执行完毕后 , int[] intArray 数组内容 : [8888, 8888, 8888, 8888, 8888]

Due to space limitations do not paste the complete code, and to download the blog with a full set of resources JNI documentation tutorials, and blog source

Published 256 original articles · won praise 1013 · Views 1.68 million +

Guess you like

Origin blog.csdn.net/han1202012/article/details/104103097