原理:
通过JNI获取java虚拟机,再获取当前程序的JNI环境,通过JNI环境获取需要调用的java类信息,再获取需要调用的java类中的函数信息。再通过JNI环境调用,使用类信息、函数信息,调用对应的java函数。
实现:
cocos2dx 封装了一个JniHelper的类,主要通过如下接口实现C++调用java
typedef struct JniMethodInfo_ { JNIEnv * env; // jclass classID; // jmethodID methodID; // } JniMethodInfo; /* methodinfo:JniMethodInfo的引用,将引用中的env,classID,methodID className: java类的完全路径 methodName: java类方法 paramCode: 类型名,在C++中使用的是简写,稍后说明下
注意:两个方法的唯一不同处,是前者调用java中的static方法,后者调用普通的方法 */ static bool getStaticMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode); static bool getMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode);
示例:
// 摘录于: cddandroidAndroidJavaEngine.cpp void AndroidJavaEngine::playBackgroundMusic(const char* filePath, bool loop) { std::string fullPath = CocosDenshion::android::getFullPathWithoutAssetsPrefix(filePath); cocos2d::JniMethodInfo methodInfo; // 判定能否获取java中的playBackgroundMusic方法 if (!getJNIStaticMethodInfo(methodInfo, "playBackgroundMusic", "(Ljava/lang/String;Z)V")) { return; } // 将C++中的char*类型通过NewStringUTF转换为Java中的jstring类型 jstring stringArg = methodInfo.env->NewStringUTF(fullPath.c_str()); // 通过JniEnv调用java中的指定方法,并将参数传进去 methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, stringArg, loop); // methodInfo.env->DeleteLocalRef(stringArg); methodInfo.env->DeleteLocalRef(methodInfo.classID); }
// 摘录:cocos2dxHelper.java public static void playBackgroundMusic(final String pPath, final boolean isLoop) { Cocos2dxHelper.sCocos2dMusic.playBackgroundMusic(pPath, isLoop); }
getStaticMethodInfo
关于getStaticMethodInfo或getMethodInfo第三个参数paramCode主要用于将C++数据按照指定格式发送到java中。
其格式为:(参数)返回类型
参数类型 | 参数简写 |
boolean | Z |
byte | B |
char | C |
short | S |
int | I |
long | J |
float | F |
double | D |
void | V |
Object | Ljava/lang/String |
Array | [Ljava/lang/String |
比如调用java中的setFPS 参数为int,返回类型为int,故此设置为:(I)I
又如,参数为4个boolean类型,返回void,则可设置为(ZZZZ)V
CallStaticIntMethod JniEnv在调用指定的java函数时,会根据java的函数返回类型选择不同的方法们。它们都有着类似的特点,比如: CallStaticVoidMethod 表示调用的是 static void 类型的方法 CallIntMethod 表示调用的是 int类型的方法 因此我们可以理解为,该方法有着这样的格式: Call[是否静态][返回类型]Method 其C++中方法中的返回类型对应的Java中的方法返回类型如下:
C++方法中函数返回类型 | java方法返回类型 |
Void | void |
Object | jobject |
Boolean | jboolean |
Byte | jbyte |
Char | jchar |
Short | jshort |
Int | jint |
Long | jlong |
Float | jfloat |
Double | jdouble |
C++类型 | Java类型 |
boolean | jboolean |
byte | jbyte |
char | jchar |
short | jshort |
int | jint |
long | jlong |
float | jfloat |
doubule | jdouble |
Object | jobject |
Class | jclass |
String | jstring |
Oject[] | jobjectArray |
boolean[] | jbooleanArray |
byte[] | jbyteArray |
char[] | jcharArray |
short[] | jshortArray |
int[] | jintArray |
long[] | jlongArray |
float[] | jfloatArray |
double[] | jdoubleArray |