JNI相关知识
JNI的意思是java本地接口,通过jni可以实现java层代码和其他语言写得代码进行互调。在cocos2d-x中,如果想要在c++层调用java层的代码,就是通过jni技术。通过调用java层的代码,我们就可以在Android平台下实现一些引擎没有提供给我们的功能,或者做一些其他的功能。比如加个广告,加个分享,调用Android原生的对话框等等吧。Cocos2d-x比较人性化的是为我们封装了jni调用的一些接口,这个类就是JniHelper,我们只需要使用这个类提供给我们的接口就可以完成调用java层代码的功能,该文件位于cocos2d/cocos/platform/android/jni目录下。
要想使用JNI,必须得包含头文件,android是使用ndk编译c/c++的,这里jni.h文件位于:\android-ndk-r8b\platforms\android-14\arch-arm\usr\include\jni.h。
JniHelper类
通过JNI获取Java虚拟机,再获取当前程序的JNI环境,通过JNI环境获取需要调用的java类信息,再获取需要调用的java类中的函数信息。再通过JNI环境调用,使用类信息、函数信息,调用对应的java函数。通过看JniHelper.cpp文件可以大致清楚这些。
头文件:
#include "platform/android/jni/JniHelper.h"
需要使用的接口如下:
static bool getStaticMethodInfo(JniMethodInfo &methodinfo,const char *className,const char *methodName,const char *paramCode); static bool getMethodInfo(JniMethodInfo &methodinfo,const char *paramCode);
//函数信息结构体 JniMethodInfo minfo; bool isHave = JniHelper::getStaticMethodInfo(minfo,/*JniMethodInfo的引用*/ "com/omega/MyApp",/*类的路径*/ "getJavaActivity",/*函数名*/ "()Ljava/lang/Object;");/*函数类型简写*/ jobject activityObj; if (isHave) { //CallStaticObjectMethod调用java函数,并把返回值赋值给activityObj activityObj = minfo.env->CallStaticObjectMethod(minfo.classID,minfo.methodID); }
getStaticMethodInfo参数详解
getMethodInfo和getStaticMethodInfo这两个接口的参数一样,意义也相同,详解如下:
java中的类型对应的简写如下:
参数类型 | 参数简写 |
boolean | Z |
byte | B |
char | C |
short | S |
int | I |
long | J |
float | F |
double | D |
void | V |
Object | Ljava/lang/Object; |
String | Ljava/lang/String; |
Array | [ |
如果函数有多个参数,直接把简写并列即可。注意Object与String型参数简写结尾的分号,示例:
- (IIII)V ==> void fun(int a,int b,int c,int d)
- (ILjava/lang/String;I)Ljava/lang/String; ==> string fun(int x,String a,int y)
- (ILjava/lang/String;[I)J ==> long fun(int n,String s,int[] arr)
通过JNIEnv进行函数调用
JNIEvn有一系列的CallStatic[返回类型]Method、Call[返回类型]Method接口,需要针对不同的函数返回类型选择调用。[返回类型]以函数返回类型的不同,对应不同的函数名。例如:
CallStaticVoidMethod ——void;
CallVoidMethod ——void
其对应关系如下:
函数名
函数返回值类型
Void
void
Object
jobject
Boolean
jboolean
Byte
jbyte
Char
jchar
Short
jshort
Int
jint
Long
jlong
Float
jfloat
Double
jdouble
参数传递
jint jX = 10; jint jY = 10; minfo.env->CallStaticVoidMethod(minfo.classID,minfo.methodID,jX,jY);
参数类型转换关系如下:
C++类型
JAVA类型
jboolean
byte
jbyte
jchar
short
jshort
jint
long
jlong
jfloat
double
jdouble
Object
jobject
Class
jclass
jstring
Object[]
jobjectArray
boolean[]
jbooleanArray
byte[]
jbyteArray
char[]
jcharArray
short[]
jshortArray
int[]
jintArray
long[]
jlongArray
float[]
jfloatArray
double[]
jdoubleArray
string类型的转换
实际上我们最常用的参数类型,主要是内建的数据类型、string字符串类型。数据类型可以直接转为j类型,但是string类型需要做如下处理:
jstring jmsg = minfo.env->NewStringUTF("http://www.baidu.com"); minfo.env->CallStaticVoidMethod(minfo.classID,jmsg);
非静态函数的调用
JniMethodInfo info; bool ret = JniHelper::getStaticMethodInfo(info,"org/cocos2dx/cpp/TestJniHelper","getObj","()Ljava/lang/Object;"); //先获得类的对象,然后用这个对象去调用它的非静态函数 jobject jobj; if(ret) { log("call static method"); jobj = info.env->CallStaticObjectMethod(info.classID,info.methodID); } //getMethodInfo判断java定义的类非静态函数是否存在,返回bool bool re = JniHelper::getMethodInfo(info,"func","()V"); if(re) { log("call no-static method"); //非静态函数调用的时候,需要的是对象,所以与静态函数调用的第一个参数不同 info.env->CallVoidMethod(jobj,info.methodID); }