JNI开发基础

JNI与NDK

  • Java和C/C++互相通过的接口,是Java语言提供的Java和C/C++相互沟通的机制,目的通过JNI可以实现java和调用本地的C/C++代码,本地的C/C++的代码也可以调用java代码。JNI 是本地编程接口。Java通过C/C++使用本地的代码的一个关键性原因在于C/C++代码的高效性。相互之间的调用。
  • NDK是一系列工具的集合。
  • 它提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。
  • 这些工具对开发者的帮助是巨大的。它集成了交叉编译器,并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。它可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作。

JNI 命名规则

对于传统的JNI编程来说,JNI方法跟Java类方法的名称之间有一定的对应关系,要遵循一定的命名规则,如下:

1) 前缀: Java_
2) 类的全限定名,用下划线进行分隔(_):com_lms_jni_JniTest
3) 方法名:getTestString
3) jni函数指定第一个参数: JNIEnv *
4) jni函数指定第二个参数: jobject
5) 实际Java参数: jstring, jint ....
6) 返回值的参数 : jstring, jint.... 所以对于在Java类 com.lms.jni.HwDemo中的一个方法:

public native String addTail(String tail);

其对应的jni层的方法如下:

jstring Java_com_lms_jni_HwDemo_addTail(JNIEnv * e, jobject clazz, jstring tail);

如果不这样命名,当把动态库加载进DVM的时候,通过JNIEnv *指针去查找Java Native方法对应的JNI方法的时候,就会找不到了。
注意,我们也可以利用函数注册的方法,将Java层的方法名跟JNI层的方法名的对应关系保存起来,注册到DVM中,就不需要这样的命名规范了。

JNI数据类型

我们知道Java的数据类型是跟C/C++的数据类型是不一样的,而JNI是处于Java和Native本地库(大部分是用C/C++写的)中间的一层,JNI对于两种不同的数据类型之间必须做一种转换,所以在JNI跟Java之间就会有数据类型的对应关系。 在JNI中,提供了以下各种数据类型,可以分为基本数据类型引用类型: 对于基本数据类型有:jchar, jbyte, jshort, jint, jlong, jfloat, jdouble, jboolean,其与java端的数据类型对应如下表:


这些基本数据类型可以在native层直接使用的


注意:
1、引用数据类型则不能直接使用,需要根据JNI函数进行相应的转换后,才能使用
2、多维数组(包括二维数组)都是引用类型,需要使用 jobjectArray 类型存取其值 ;
例如:二维整型数组就是指向一位数组的数组,其声明使用方式如下:
//获得一维数组 的类引用,即jintArray类型

    jclass intArrayClass = env->FindClass("[I"); 

//构造一个指向jintArray类一维数组的对象数组,该对象数组初始大小为dimion

jobjectArray obejctIntArray  =  env->NewObjectArray(dimion ,intArrayClass , NULL);
jni中类的继承关系

JNI方法签名

1、基本类型的描述符已经被定义好了,如下表所示:


这里容易搞混淆的是Boolean和long为什么不取首字母。因为byte已经是B,所以B被占了,Boolean选择用Z。Long为什么不用L,因为L表示对象,被占用,选择用J

2、引用类型的描述符

  • 一般引用类型则为 L + 该类型类描述符 + ; (注意,这儿的分号“;”只得是JNI的一部分,而不是我们汉语中的分段,下同)
    例如:String类型的域描述符为 Ljava/lang/String;

  • 对于数组,其为 : [ + 其类型的域描述符 + ;
    int[ ] 其描述符为[I
    float[ ] 其描述符为[F
    String[ ] 其描述符为[Ljava/lang/String;
    Object[ ]类型的域描述符为[Ljava/lang/Object;

  • 多维数组则是 n个[ +该类型的域描述符 , N代表的是几维数组。例如:
    int [ ][ ] 其描述符为[[I
    float[ ][ ] 其描述符为[[F

  • 对于上面的类,要注意其后面还有一个分号。而对一个方法,其签名就是其参数类型签名和返回值类型签名的字符串,其形式如下:(类型签名1类型签名2...)返回值类型签名
    例↓↓↓↓↓↓

方法 1):public string addTail(String tail, int index)

其对应的签名:(Ljava/util/String;I)Ljava/util/String;

方法 2):public int addValue(int index, String value,int[] arr)

其对应的签名 :(ILjava/util/String;[I)I


你可能感兴趣的:(JNI开发基础)