本文是JNI系列的第二篇,介绍JNI中的基本数据类型,以及Java和native的传递约定。
系列文章的大纲如下:
- JNI 简介
- JNI 基本类型
- JNI String
- JNI 数组
- JNI 实例变量
- JNI 静态变量
- JNI 回调实例方法与静态方法
- JNI 调用Java中的super.method()
- JNI 中创建对象
- JNI 中创建对象数组
- JNI 中局部引用和全局引用
- JNI 动态注册
- 使用Android NDK编译Android的Native库
JNI中的基本数据类型
JNI中的基本类型也称为Native基本类型。
在Java中的基本类型与JNI中的基本类型的对应关系如下:
Java类型 | Native类型 | 说明 |
---|---|---|
boolean | jboolean | unsigned 8 bits |
byte | jbyte | signed 8 bits |
char | jchar | unsigned 16 bits |
short | jshort | signed 16 bits |
int | jint | signed 32 bits |
long | jlong | signed 64 bits |
float | jfloat | 32 bits |
double | jdouble | 64 bits |
void | void | N/A |
在Native中定义了jboolean
的两个取值:
#define JNI_FALSE 0
#define JNI_TRUE 1
同时还定义jsize
类型用于处理索引以及大小:
typedef jint jsize;
以上就是native中的基本类型,以及与Java中基本类型的对应关系,下面就一起来看看如何在Java与native中进行传递吧!
传递基本类型参数
在JNI简介中完整的介绍了如果在Java中调用native中的函数。但是并没有传递参数。 在Java与native间传递基本数据类型是十分简单而又直接的,在Java的native方法的参数和返回值,在生成的头文件的函数签名中使用上一节介绍的对应的native类型进行替换,在C/C++的实现中直接使用即可。
实例
我们来看一个实例。
Hello.java
package myjni;
public class Hello {
static {
System.loadLibrary("hello");
}
public native short addShort(short a, short b);
public static void main(String[] args) {
Hello hello = new Hello();
short a = 1;
short b = 2;
System.out.println("addShort(" + a + ", " + b + ") = " + hello.addShort(a, b));
}
}
如果还不清楚如果生成头文件请参考JNI简介。
生成头文件myjni_Hello.h
的签名为:
/*
* Class: myjni_Hello
* Method: addShort
* Signature: (SS)S
*/
JNIEXPORT jshort JNICALL Java_myjni_Hello_addShort
(JNIEnv *, jobject, jshort, jshort);
实现函数Java_myjni_Hello_addShort
:
JNIEXPORT jshort JNICALL Java_myjni_Hello_addShort(JNIEnv *env, jobject obj, jshort ja, jshort jb) {
jshort ret = ja + jb;
return ret;
}
编译生成动态库,并运行Java程序得到输出:
addShort(1, 2) = 3
传递其他数据类型也是一样的操作。注意如果返回true
或者false
,在native代码中直接使用JNI_FALSE
或者JNI_TRUE
。
类型签名
在生成的头文件中,函数会有如下的注释:
/*
* Class: myjni_Hello
* Method: addShort
* Signature: (SS)S
*/
Class和Method的值很容易理解,Signature的值(SS)S是什么含义呢?
这其实是JVM中的类型的表示方法,有如下对应关系:
类型签名 | Java类型 |
---|---|
Z | boolean |
B | byte |
C | char |
S | short |
I | int |
J | long |
f | float |
D | double |
V | void |
Lfully-qualified-class; | fully-qualified-class |
[type | type[] |
(arg-types)ret-type | method type |
上表中单个大写字母很好理解,其中的V
用于函数返回值。
对于fully-qualified-class
,看例子来理解,Java中的String类型的类型签名为Ljava/lang/String;
,开头为L
,结尾是;
。
对于Java中的数组,如int[]
,类型签名为[I
。
最后一个表示方法的签名,如(SS)S
,表示函数参数是两个short
类型,返回值是short
。
括号内SS
是函数的参数类型,括号外的S
是函数的返回值类型。
如Java中的方法:
long f (int n, String s, int[] arr);
类型签名为:
(ILjava/lang/String;[I)J
vx搜:极客Furzoom,关注获取第一手资料。
本文完。