2.4.2 数据类型转换
前面的分析解决了JNI函数的注册问题,下面来研究数据类型转换的问题。
在Java中调用native函数传递的参数是Java数据类型,那么这些参数类型到了JNI层会变成什么呢?
Java数据类型分为基本数据类型和引用数据类型两种,JNI层也是区别对待这二者的。先来看基本数据类型的转换。
1.基本数据类型的转换
基本数据类型的转换很简单,可用表2-1表示:
上面列出了Java基本数据类型与JNI层数据类型对应的转换关系,非常简单。不过,务必注意转换成Native类型后对应数据类型的字长,例如jchar在Native语言中是16位,占两个字节,这和普通的char占一个字节的情况是完全不一样的。
接下来看Java引用数据类型的转换。
2.引用数据类型的转换
引用数据类型的转换如表2-2所示:
由上表可知:除了Java中基本数据类型的数组、Class、String和Throwable外,其余所有Java对象的数据类型在JNI中都用jobject表示。
这一点太让人惊讶了!看看processFile这个函数:
//Java层processFile有三个参数。
processFile(String path,String mimeType,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。