就语法而言,JNI的API是C语言的,因而了解API就可以使用JNI了。JNI的意图是为消除JAVA、C之间的通信障碍,以便取长补短。Java是纯面向对象语言,除了基本数据类型外,其它的都是引用数据类型。引用数据类型往往是一个类,类中包含了域(field),方法(method)以及类这个整体本身。正因如此,JNI提供了C的API来处理Java中的类。先look几个常用的API
jclass FindClass(const char* name);
/*找到某个名称为name的类,name是类的完整名称,比如com.processplayer.Process的完整名称为com/processpalyer/Process*/
jfieldID GetFieldID(jclass clazz, const char* name, const char* sig);
/*取得clazz类的名为name的field*/
jmethodID GetMethodID(jclass clazz, const char* name, const char* sig);
/*取得clazz类的名为name的method*/
注:
sig是
signature的缩写。
1.引用类型的signature以L开头,后接类的完整地址,并以;结尾。例如,
Lcom/processpalyer/Process;
2.基本数据类型的signature,如下表
boolean--- Z,byte ---B,char ---C,short --- S,int--- I,long ---J(不用L的原因可能是为了避免与引用类型冲突),float--- F,double ---D
3.数组类型的signature以[开头,后接基本数据类型(或者引用类型)的signature。例如,
int[]的signature为[I
Process[]的signature为[Lcom/processpalyer/Process;
多维的数据类型,每多一维,多加一个[。例如,
int[][]的signatrue为[[I
理解signature之后,就可以很方便得使用GetFieldID取得类的field
4.方法的signature,只需要指定方法的参数类型和返回值类型就OK了。在一对圆括号内连续放置函数参数的signature,在这对括号的右边放置返回值类型的signature。例如,
int GetProcess(int, String)的signature为(ILjava/lang/String;)I
void GetProcess()的signature为()V,返回值为空用V表示
构造函数的name为<init>,返回值类型的signature为V
创建自定义的java类
-
在jni内找到需要创建的java类。Jni中任何一个类都可以用jclass来标识
jclass processClazz = env->FindClass("swu/processplayer/processlist/Process")
-
获取类的构造函数
jmethodID constructMethod = env->GetMethodID(processClazz, “<init>”,“(Ljava/lang/String;I)V”);
-
创建类实例
jstring processName = env->NewStringUTF(“Erase”);
jintframeNum = 10;
jobject processObject = env->NewObject(processClazz, constructMethod,processName, frameNum);
-
调用类的方法以改变类的状态
-
获取方法
jmethodID resetMethod = env->GetMethodID(processClazz, “reset”,“()V”);
-
调用方法
env->CallVoidMethod(processObject,resetMethod);
注:根据方法的返回值不同需要调用不同的Call***Method
-
方便用法
-
查看类的signature
首先cd到生成的class.dex文件目录,然后javap-s -p classname可以打印出类的完整信息,包括域的signature和方法的signature。
-
其它
关键点小结
-
创建类实例仅能使用NewObject一个方法,但是调用类方法却要根据返回值调用不同的Call***Method方法。
-
创建String对象,可方便得调用NewStringUTF函数
-
获取MethodID时,构造函数的name为”<init>”
-