JNI系列文章:
JNI系列之入门Hello JNI C(一)
JNI系列之入门Hello JNI C(二)
JNI系列入门之C语言与Java的双向通信(一)
JNI系列入门之C语言与Java的双向通信(二)
JNI系列入门之C语言中文字符串乱码问题
即上一篇JNI系列之入门Hello JNI C(一)简单介绍后,这篇将详细讲解C中的所有代码。
- 理解C中native函数实现的意思
我们来看生成出来的native函数声明
/*
* Class: com_jerry_jnitest_JniTest
* Method: getStringFromC
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_jerry_jnitest_JniTest_getStringFromC
(JNIEnv *, jclass);
- Java_com_jerry_jnitest_JniTest_getStringFromC这一长串是函数名,它是有规律的:
Java_native方法在java类中的包名全称_native的方法名
原来java里native方法:
public native static String getStringFromC();
-
再来看返回值 jstring,对应的是java中native方法的返回值String,通过VS右击它转到定义,会发现它就是一个_jobject结构体指针变量jobject的别名:
Paste_Image.png -
参数JNIEnv *,它在java的native方法里没有对应的参数,这个是JNI接口函数特有的,包括后面的jclass或者jobject是必须有的两个参数。
JNIEnv *是个啥玩意呢,通过VS转到定义:
Paste_Image.png
有两个地方都声明了:
一个是C++的,一个是C的。
C中是结构体指针struct JNINativeInterface_ *的一个别名,那就说明JNIEnv *就是一个二级指针类型。
C++中:
Paste_Image.png
图中可以看到JNIEnv是JNIEnv_的一个别名,而JNIEnv_是个结构体,里面JNINativeInterface_ *function作为它的一个成员变量,图中可以看到C++对function的函数封装了一层,参数传了this,也就是当前functions这个结构体指针其实就是上文C中JNIEnv这个JNINativeInterface_ *结构体指针的别名。那意思就很明白了,在c++中native函数的JNIEnv *就是一级指针。
至于C中为什么要用二级指针,应该是结构体中的那些函数指针的具体实现都需要用到JNINativeInterface_ *这个结构体指针吧。(这段话比较拗口,会比较难理解,可以多看看思考思考)
native函数中,第二个参数jclass,看看它的定义:
Paste_Image.png
其实它的意思就是相对于java的Class类型,因为我们在Java中写的native方法是 static修饰的所以直接是类类型来访问应用这个native方法。
如果java中改成:
public native String getStringOfC(String input);
那就变成了:
JNIEXPORT jstring JNICALL Java_com_jerry_jnitest_JniTest_getStringOfC
(JNIEnv *env, jobject jobj, jstring jstr){
}
这里面jobject标示这个native方法是调用它的对象,第三个参数jstring就是java方法中String input这个参数。
从上文可以看出,jxxxx的都会对应Java中的一种数据类型。
下面是Java的数据类型与JNI的数据类型的映射关系:
Java数据类型 | Jni数据类型 | C数据类型 |
---|---|---|
基础数据类型 | ||
void | void | void |
boolean | jboolean | unsigned char |
byte | jbyte | signed char |
char | jchar | char |
short | jshort | short |
int | jint | int |
long | jlong | __int64(long long) |
float | jfloat | float |
double | jdouble | double |
引用数据类型 | ||
String | jstring (jobject的别名) | struct _jobject* |
Object | jobject | struct _jobject* |
基本数据类型的数组 | ||
blooean[] | jbooleanArray 1. jbooleanArray是jarray的别名 2. jarray又是jobject的别名 |
struct _jobject * |
byte[] | jbyteArray 1. jbyteArray是jarray的别名 2. jarray又是jobject的别名 |
struct _jobject * |
char[] | jcharArray 1. jcharArray是jarray的别名 2. jarray又是jobject的别名 |
struct _jobject * |
short[] | jshortArray 1. jshortArray是jarray的别名 2. jarray又是jobject的别名 |
struct _jobject * |
int[] | jintArray 1. jintArray是jarray的别名 2. jarray又是jobject的别名 |
struct _jobject * |
long[] | jlongArray 1. jlongArray是jarray的别名 2. jarray又是jobject的别名 |
struct _jobject * |
float[] | jfloatArray 1. jfloatArray是jarray的别名 2. jarray又是jobject的别名 |
struct _jobject * |
double[] | jdoubleArray 1. jdoubleArray是jarray的别名 2. jarray又是jobject的别名 |
struct _jobject * |
引用数据类型数组 | ||
Object[] | jobjectArray 1. jobjectArray是jarray的别名 2. jarray又是jobject的别名 |
struct _jobject * |
JNI系列文章:
JNI系列之入门Hello JNI C(一)
JNI系列之入门Hello JNI C(二)
JNI系列入门之C语言与Java的双向通信(一)
JNI系列入门之C语言与Java的双向通信(二)
JNI系列入门之C语言中文字符串乱码问题
网友评论