cocos2d-x c 调用java_cocos2d-x中使用JNI的调用JAVA方法

用cocos2d-x发布Android项目时,都应该知道要用JAVA与C/C++进行交互时会涉及到JNI的操作(Java Native Interface)。JNI是JAVA的一个通用接口,旨在本地化语言(如CC++)与JAVA语言进行交互,在交互过程成中,JAVA调用的是已编译好的本地化语言的二进制代码(如Windows下的dll,Linux下的so文件),所以在交叉编译时看到Eclipse的控制台输出

[armeabi] SharedLibrary  : libcocos2dcpp.so

[armeabi] Install        : libcocos2dcpp.so => libs/armeabi/libcocos2dcpp.so

时即可认为cocos2d-x项目在Android平台编译成功,其原理就是生成这个二进制文件(动态连接库)与Android的本地语言———JAVA进行交互,而交互的过程需要一个中间的桥梁,这个桥梁就是JNI。

那么接下来就记录下如何在cocos2d-x中用C++中使用JNI调用Java语言的中的成员方法或静态方法。

在cocos2d-x中有个已封装好的用于方便操作操作JNI的类——JniHelper,主要通过以下两个函数来获取JAVA类的信息。

staticboolgetStaticMethodInfo(JniMethodInfo &methodinfo,constchar*className,constchar*methodName,constchar*paramCode);

staticboolgetMethodInfo(JniMethodInfo &methodinfo,constchar*className,constchar*methodName,constchar*paramCode);顾名思义,第一个函数是获取静态方法的信息,第二个是获取成员方法的信息。其参数都是一致的分别是

methodinfo:JniMethodInfo类的引用

className:类的路径(即包名加类名)

methodName:方法名

paramCode:方法的参数类型和返回值类型

其中的第四个参数的编写规则大致如下:

(参数类型...)返回值类型。

编写规则可以参照oracle的官方文档 http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html

在c++数据类型映射到java数据类型时已以下的一个联合体方式来定义

typedefunionjvalue {

jboolean z;

jbyte    b;

jchar    c;

jshort   s;

jint     i;

jlong    j;

jfloat   f;

jdouble  d;

jobject  l;

} jvalue;

可以看到,这个union包含了映射JAVA的8个原声数据类型和一个自定义类型,这样就囊括了JAVA所有的数据类型的映射。

而且,JAVA VM(JAVA虚拟机)还定义了一下的签名来表明JAVA的数据类型

Z    boolean

B    byte

C    char

S    shot

I    int

J    long

F    float

D    double

L fully-qualified-class;    fully-qualified-class(注意分号)

[type    type[]

(arg-types)ret-type    method type

举个例子来说

如果想调用一下的一个JAVA方法

long f(int n, String s, int[] arr);

那么第四个参数(paramCode)可以写为

(ILjava/lang/String;[I)J

当然,上面的命名规则也可以通过JAVA反编译来获取。

b3e487b54d6ae539b8a5cbdf9d27a770.png

从上图就可以看出一个类的所有方法签名,由此也解释了JAVA虚拟机在解析JAVA字节码时就是通过上面的方法签名来找到相应的方法入口地址。

接下来来测试通过JniHelper来帮助实现c++调用一个带有参数和返回值的静态JAVA方法的过程

1. 创建一个新的cocos2d-x项目,然后拿到Eclipse上去编译。编译完成后编辑入口类,加入我们要测试的JAVA代码

packagecom.cocos2dx.TestJNI;

importorg.cocos2dx.lib.Cocos2dxActivity;

importorg.cocos2dx.lib.Cocos2dxGLSurfaceView;

importandroid.os.Bundle;

publicclassTestJNIextendsCocos2dxActivity{

protectedvoidonCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

}

publicCocos2dxGLSurfaceView onCreateView() {

Cocos2dxGLSurfaceView glSurfaceView = newCocos2dxGLSurfaceView(this);

// TestJNI should create stencil buffer

glSurfaceView.setEGLConfigChooser(5,6,5,0,16,8);

returnglSurfaceView;

}

static{

System.loadLibrary("cocos2dcpp");

}

/加入JAVA测试代码/

publicstaticString staticMethod(inti, String str,doubled) {

return"i: "+ i +", str: "+ str +", d: "+ d;

}

}

2. 修改HelloWorldScene.cpp,加入jni的调用代码

#include "HelloWorldScene.h"

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

#include 

#include "platform/android/jni/JniHelper.h"

#endif

USING_NS_CC;

CCScene* HelloWorld::scene() {

CCScene *scene = CCScene::create();

HelloWorld *layer = HelloWorld::create();

scene->addChild(layer);

returnscene;

}

boolHelloWorld::init() {

if(!CCLayer::init()) {

returnfalse;

}

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

JniMethodInfo methodInfo;

//判断方法是否存在

boolisExist = JniHelper::getStaticMethodInfo(methodInfo,"com/cocos2dx/TestJNI/TestJNI","staticMethod","(ILjava/lang/String;D)Ljava/lang/String;");

if(isExist) {

jint i = 0;

jdouble d = 1.22;

jstring str = methodInfo.env->NewStringUTF("Test Static Method");//创建

jstring s = (jstring)methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID, i, str, d);//调用Java方法

constchar* c = methodInfo.env->GetStringUTFChars(s, 0);//将jstring转成字符指针

//把返回的字符串显示在屏幕中

CCLabelTTF* ttf = CCLabelTTF::create(c, "Arial", 30);

ttf->setPosition(ccp(300, 160));

this->addChild(ttf);

//释放内存

methodInfo.env->ReleaseStringUTFChars(s, c);

methodInfo.env->DeleteLocalRef(str);

}else{

CCLog("share error");

}

#endif

returntrue;

}

运行结果就可以看到调用成功:

29bdbb2e5791c5edd21a0bc8fb51add0.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值