💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
通过前面的分析,解决了JNI函数的注册问题。下面来研究数据类型转换的问题。 在Java中调用native函数传递的参数是Java数据类型,那么这些参数类型到了JNI层会变成什么呢? Java数据类型分为基本数据类型和引用数据类型两种,JNI层也是区别对待这二者的。先来看基本数据类型的转换。 (1)基本类型的转换 基本类型的转换很简单,可用表2-1表示: :-: 表2-1 基本数据类型转换关系表 | Java | Native类型 | 符号属性 | 字长 | | --- | --- | --- | --- | |boolean | jboolean | 无符号 | 8位 | | byte | jbyte | 无符号 | 8位 | | char | jchar | 无符号| 16位 | | short | jshort | 有符号| 16位 | | int | jint |有符号 | 32位 | | long | jlong | 有符号 | 64位 | | float | jfloat | 有符号 | 32位 | | double | jdouble| 有符号 | 64位 | 上面列出了Java基本数据类型和JNI层数据类型对应的转换关系,非常简单。不过,应务必注意,转换成Native类型后对应数据类型的字长,例如jchar在Native语言中是16位,占两个字节,这和普通的char占一个字节的情况完全不一样。 接下来看Java引用数据类型的转换。 (2)引用数据类型的转换 引用数据类型的转换如表2-2所示: :-: 表2-2 Java引用数据类型转换关系表 | Java引用类型 | Native类型 | Java引用类型 | Native类型 | | --- | --- | --- | --- | | All objects | jobject | char[] |jcharArray | | java.lang.Class实例 | jclass | short[] | jshortArray | | java.lang.String实例 | jstring | int[] | jintArray | | Object[] | jobjectArray | long[] | jlongArray | | boolean[] | jbooleanArray | float[] | floatArray | | byte[] |jbyteArray | double[] | jdoubleArray | | java.lang.Throwable实例 | jthrowable | | | 由上表可知: - 除了Java中基本数据类型的数组、Class、String和Throwable外,其余所有Java对象的数据类型在JNI中都用jobject表示。 这一点太让人惊讶了!看processFile这个函数: ~~~ //Java层processFile有三个参数。 processFile(String path, StringmimeType,MediaScannerClient client); //JNI层对应的函数,最后三个参数和processFile的参数对应。 android_media_MediaScanner_processFile(JNIEnv*env, jobject thiz, jstring path, jstring mimeType, jobject client) ~~~ 从上面这段代码中可以发现: - Java的String类型在JNI层对应为jstring。 - Java的MediaScannerClient类型在JNI层对应为jobject。 如果对象类型都用jobject表示,就好比是Native层的void*类型一样,对码农来说,是完全透明的。既然是透明的,那该如何使用和操作它们呢?在回答这个问题之前,再来仔细看看上面那个android_media_MediaScanner_processFile函数,代码如下: ~~~ /* Java中的processFile只有三个参数,为什么JNI层对应的函数会有五个参数呢?第一个参数中的JNIEnv是什么?稍后介绍。第二个参数jobject代表Java层的MediaScanner对象,它表示 是在哪个MediaScanner对象上调用的processFile。如果Java层是static函数的话,那么 这个参数将是jclass,表示是在调用哪个Java Class的静态函数。 */ android_media_MediaScanner_processFile(JNIEnv*env, jobject thiz, jstring path, jstring mimeType, jobject client) ~~~ 上面的代码,引出了下面几节的主角JNIEnv。