JNI - JAVA 数据类型转换



基本数据类型转换

在 Java 中传递的参数类型是 int,而在 JNI 中就成了 jint,这就涉及到 Java 到 JNI 的数据类型转换。

Java 类型 Native 类型 字节长度
boolean jboolean 8位
byte jbyte 8位
char jchar 16位
short jshort 16位
int jnit 32位
long jlong 64位
float jfloat 32位
double jdouble 64位

引用数据类型转换

除了基本数据类型之外,引用数据类型也有着一一对应。

Java 类型 Native 类型
objects jobject
java.lang.Class jclass
java.lang.String jstring
Object[] jobjectArray
boolean[] jbooleanArray
byte[] jbyteArray
char[] jcharArray
short[] jshortArray
int[] jintArray
long[] jlongArray
float[] jfloatArray
double[] jdoubleArray
java.lang.Throwable jthrowable

除了 Java 中基本数据类型的数组、Class、String 和 Throwable 外,其余所有 Java 对象的数据类型在 JNI 中都用 jobject 表示。

String 字符串操作

对于基本数据类型的操作,比如 boolean、int、float 等都大同小异,无非是在原来的数据类型前面加了一个 j来表示 JNI 数据类型。
而对于 String 类型,必须要使用合适的 JNI 函数来将 jstring 转变成 C/C++ 字符串。
对于下面的 Native 方法,传入一个字符串,并要求返回一个字符串。

external fun stringFromJNI(): String

layout1Binding.tv1.setOnLongClickListener {
    
    
       val str = strFromJNI("我是Java向C传递的参数")
       layout1Binding.tv1.text = str
        true

        }

生成的对应的 C++ 代码如下:

extern "C"
JNIEXPORT jstring JNICALL
Java_com_znzy_myapplication_MainActivity_strFromJNI(JNIEnv *env, jobject thiz, jstring string) {
    
    
    // 生成jstring
    jstring returnValue = env->NewStringUTF("Hello Best");
    // 把jstring类型的字符串转换为C风格的字符串,会额外申请内存
    const char *str = env->GetStringUTFChars(string,0);
    // 做检查判断
    if (str == NULL){
    
    
        return NULL;
    }
    // 实际操作
    printf("%s",str);
    LOGE("%s",str);
    //释放申请的内存
    env->ReleaseStringUTFChars(string,str);
    return returnValue;
}

通过Java调用验证发现日志正常输出,页面正常显示

在这里插入图片描述

Java 层的字符串到了 JNI 就成了 jstring 类型的,但 jstring 指向的是 JVM 内部的一个字符串,它不是 C 风格的字符串 char*,所以不能像使用 C 风格字符串一样来使用 jstring 。

JNI 支持将 jstring 转换成 UTF 编码和 Unicode 编码两种。因为 Java 默认使用 Unicode 编码,而 C/C++ 默认使用 UTF 编码。
将 jstring 转换成 UTF 编码的字符串

  • GetStringUTFChars(jstring string, jboolean* isCopy)

其中,jstring 类型参数就是我们需要转换的字符串,而 isCopy 参数的值为 JNI_TRUE 或者 JNI_FALSE ,代表是否返回 JVM 源字符串的一份拷贝。如果为JNI_TRUE 则返回拷贝,并且要为产生的字符串拷贝分配内存空间;如果为JNI_FALSE就直接返回了JVM 源字符串的指针,意味着可以通过指针修改源字符串的内容,但这就违反了 Java 中字符串不能修改的规定,在实际开发中,直接填 NULL就好了。

当调用完GetStringUTFChars 方法时别忘了做完全检查。因为 JVM 需要为产生的新字符串分配内存空间,如果分配失败就会返回 NULL,并且会抛出 OutOfMemoryError 异常,所以要对 GetStringUTFChars 结果进行判断。

当使用完 UTF 编码的字符串时,还不能忘了释放所申请的内存空间。调用 ReleaseStringUTFChars 方法进行释放。

除了将 jstring 转换为 C 风格字符串,JNI 还提供了将 C 风格字符串转换为 jstring 类型。

通过 NewStringUTF函数可以将 UTF 编码的 C 风格字符串转换为 jstring 类型,通过NewString 函数可以将 Unicode 编码的 C 风格字符串转换为 jstring 类型。这个 jstring 类型会自动转换成 Java 支持的 Unicode 编码格式。

除了 jstring 和 C 风格字符串的相互转换之外,JNI 还提供了其他的函数。

String 字符串函数操作总结

JNI 函数 描述
GetStringChars / ReleaseStringChars 获得或释放一个指向 Unicode 编码的字符串的指针(指 C/C++ 字符串)
GetStringUTFChars / ReleaseStringUTFChars 获得或释放一个指向 UTF-8 编码的字符串的指针(指 C/C++ 字符串)
GetStringLength 返回 Unicode 编码的字符串的长度
getStringUTFLength 返回 UTF-8 编码的字符串的长度
NewString 将 Unicode 编码的 C/C++ 字符串转换为 Java 字符串
NewStringUTF 将 UTF-8 编码的 C/C++ 字符串转换为 Java 字符串
GetStringCritical / ReleaseStringCritical 获得或释放一个指向字符串内容的指针(指 Java 字符串)
GetStringRegion 获取或者设置 Unicode 编码的字符串的指定范围的内容
GetStringUTFRegion 获取或者设置 UTF-8 编码的字符串的指定范围的内容

猜你喜欢

转载自blog.csdn.net/TLuffy/article/details/123994246