穿裤衩闯天下

Cocos2d-x 3.x 开发之让C++通过jni调用java中的方法为后续添加第三方sdk做准备

Cocos2d-x是用C++写的引擎,可以跨平台,既然可以跨平台那么我们肯定会移植到特定的平台上,比如我就是做Android开发的,所以我做的游戏大多都要移植到Android平台,以后或许会开发ios平台,那都是后话了;

移植到Android平台后有时需要进行底层和上层的交互,比如为Cocos2d-x开发的Android游戏添加广告、分享等功能时,需要用到第三方sdk,这就要让C++java代码进行互相调用了,google是有提供jni接口来实现他们的互相调用的;
这里有一篇文章Cocos2d-x 3.x 开发之添加游戏截图分享到新浪微博

废话不多说,开始办正事:
我的开发环境:

VS:2012
Eclipse:3.7.1
Jdk:1.7
SDK:23.0
Python:2.7.6
Cocos2d-x:3.2

准备工作

要使用jni,就要在cpp类中引入jni的包,但是在VS中使用#include <jni>时提示找不到jni库文件,这让我很是蛋疼,最后搜索了好久终于找到了解决办法:

`右击项目`->`属性`->`配置属性`->`VC++目录`->`包含目录`:

在这个选项内添加你的jdk下的include目录和include下的win32目录,然后就OK了
image_jni_h

定义方法

解决了这个问题就可以继续了:
首先创建一个MyJniFunc.h文件,并在引入库文件时添加平台判断代码,只有在Android平台下在引入jni库,因为jni毕竟是只有Android才用的玩意:

1
2
3
4
5
6
7
8
9
10
11
12
#if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include <jni .h>
#include "platform/android/jni/JniHelper.h"
#endif
#include "cocos2d.h"
USING_NS_CC;
class MyJniFunc {
public:
static void testJniMethod(int i);
};

在C++中实现方法

接着就是在cpp文件中实现所定义的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "MyJniFunc.h"
USING_NS_CC;
void MyJniFunc::testJniMethod(int i){
#if(CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
log("win32 is not use jni!");
#endif
#if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
log("testJniMethod %d", i);
JniMethodInfo methodInfo;
bool isHave = JniHelper::getStaticMethodInfo(methodInfo, "com.lzan13.game.hello.HelloActivity", "testJniMethod", "(I)V");
if(isHave){
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, i);
}
#endif
}

其中getStaticMethodInfo()就是获得你要调用的java类中的静态方法,其中有四个参数:

1、JniMethodInfo:就是保存方法信息
2、你要调用的方法所在的类的完全路径(包名+类名)
3、方法名
4、方法需要的参数类型和返回值类型(可以传递多种参数类型)

Jni和Java数据类型对应关系

下边列出jnijava的数据类型对应关系:

jni类型签名 jni的数据类型 java的数据类型
V void void
Z jboolean boolean
I jint int
J jlong long
D jdouble double
F jfloat float
B jbyte byte
C jchar char
S jshort short
Ljava/long/String; jstring String

这里边String是个比较特殊的类型,他的写法是前边以L开头,后边以;结尾,中间加上以/分割的包名
结合这个对照表就可以看出我调用的java方法是传递了一个int类型的参数,返回值为void
如果要传递多个参数,可以直接写在一起,比如(ILjava/long/String;)V就是传递一个int和一个String的参数,返回为void

定义Java方法

接着就是要在java中定义好在C++中要调用的方法:

1
2
3
4
5
6
7
8
public static void testJniMethod(int i) {
switch (i) {
case 0:
//判断传进来的参数
Log.i("lzan13", "test jni method!");
break;
}
}

然后就是 编译运行,要在手机上测试,不然win32是不会调用这段代码的!看到log输出信息就说明调用成功了!

阿弥陀佛,施主,来个馒头吧 😋 ~