JNI系列入门之Hello JNI C(二)

1,579 阅读3分钟

JNI系列文章:

  1. JNI系列之入门Hello JNI C(一)
  2. JNI系列之入门Hello JNI C(二)
  3. JNI系列入门之C语言与Java的双向通信(一)
  4. JNI系列入门之C语言与Java的双向通信(二)
  5. 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);
  1. Java_com_jerry_jnitest_JniTest_getStringFromC这一长串是函数名,它是有规律的: Java_native方法在java类中的包名全称_native的方法名 原来java里native方法:
public native static String getStringFromC();
  1. 再来看返回值 jstring,对应的是java中native方法的返回值String,通过VS右击它转到定义,会发现它就是一个_jobject结构体指针变量jobject的别名:
    Paste_Image.png
  2. 参数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系列文章:

  1. JNI系列之入门Hello JNI C(一)
  2. JNI系列之入门Hello JNI C(二)
  3. JNI系列入门之C语言与Java的双向通信(一)
  4. JNI系列入门之C语言与Java的双向通信(二)
  5. JNI系列入门之C语言中文字符串乱码问题