接上一篇关于JNI的基本入门Java通过JNI调用C/C++动态链接库之HelloWorld,简述给JNI函数传递参数,以及通过JNI函数返回值的方式。
JNI类型映射
首先来回顾一下上一篇基础文章中通过javah生成的头文件的以下内容:
/*
* Class: hello
* Method: helloWorld
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_hello_helloWorld
(JNIEnv *, jobject);
发现注释中给出了类名hello,是我们JAVA程序的类名,后面跟着方法名以及方法的签名,注意方法的签名类型为()V,表示该方法不接收任何参数,且返回类型为void,即没有返回值。
JNI定义了一些基本类型用于在java与native代码之间的映射,这些基本类型都是j开头,后面跟java中的实际类型,具体的基本类型及方法签名类型如下表所示:
方法签名的形式即为(参数签名)返回值类型签名。例如一个形如double func(int a, int b)的方法签名为(II)D
另外还有几个比较特殊的签名,如object签名为L{用/分割的完整类名}如Ljava/lang/String表示一个String对象。Array的签名为[{相应类型的签名},如[D,表示类型为D的数组,[Ljava/lang/String表示String对象的数组。
当然JNI也定义了很多引用类型的映射,其中jobject对应于java.lang.Object,以及其之类型:
jclass—java.lang.Class
jstring—java.lang.String
jthrowable—java.lang.Throwable
jarray与java中的Array对应,由于Array在java中支持8种基本数据类型,所以相应的有8种Array,分别为jintArray、jbyteArray、jshortArray、jlongArray、jfloatArray、jdoubleArray、jcharArray和jbooleanArray。以及一个对象类型的Array:jobjectArray。
查看jni.h头文件会发现里面都是使用typedef进行的定义:
// 头文件"jni.h"中的声明
typedef unsigned char jboolean;
typedef unsigned short jchar;
typedef short jshort;
typedef float jfloat;
typedef double jdouble;
typedef jint jsize;
struct _jobject;
typedef struct _jobject *jobject;
typedef jobject jclass;
typedef jobject jthrowable;
typedef jobject jstring;
typedef jobject jarray;
typedef jarray jbooleanArray;
typedef jarray jbyteArray;
typedef jarray jcharArray;
typedef jarray jshortArray;
typedef jarray jintArray;
typedef jarray jlongArray;
typedef jarray jfloatArray;
typedef jarray jdoubleArray;
typedef jarray jobjectArray;
//"linux/jni_mh.h"中的声明
typedef int jint;
#ifdef _LP64 /* 64-bit Solaris */
typedef long jlong;
#else
typedef long long jlong;
#endif
typedef signed char jbyte;
现在可以清楚的知道JNI在java代码和native代码之间做了类型转换,以使两种语言之间的数据类型可以互通。
基本类型参数传递
举一个例子说明,程序的功能为给java程序传递两个int做为参数,将该参数传递给native函数,native函数累加两个参数之间的数字,然后取平均后将结果返回给java程序并输出。
java代码
//TestJint.java
public class TestJint
{
static {
System.loadLibrary("myjint"); //载入本地的动态链接库
}
private native double avg(int a, int b); //声明一个本地方法,接受2个int变量做为参数,返回其double类型的累加和的平均值
public static void main(String args[]) {
if (args.length