Cocos2d-x   发布时间:2022-05-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了Cocos2d-x利用jni调用java层代码大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

jni的意思是java本地调用,通过jni可以实现java层代码和其他语言写得代码进行交互。在Cocos2d-x中,如果想要在C++层调用java层的代码,就是通过jni技术。通过调用java层的代码,我们就可以在Android平台下实现一些引擎没有提供给我们的功能,或者做一些其他的功能。比如加个广告,加个分享,调用Android原生的对话框等等吧。Cocos2d-x比较人性化的是为我们封装了jni调用的一些接口,这个类就是JniHelper,我们只需要使用这个类提供给我们的接口就可以完成调用java层代码的功能。先说一下这个类的位置,因为自己在找的时候有点犯二,所以特意说明一下。在3.0和3.1以上的引擎版本中,这个类的位置分别如下。

3.1以后引擎把原来cocos目录下的包含各个功能的文件夹都放到了cocos目录下,我个人认为这样的放法还是比较好的。就是引擎老改目录,希望以后不要放来放去了。最主要的当然是看看怎么使用JniHelper这个类了。


首先使用之前要包含头文件,写法如下,记住要加上条件编译,这个东西是Android平台下才用到。

1
2
3
4
5
6
#if(CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID)
#include"platform/android/jni/JniHelper.h"
#include<jni.h>
@H_674_46@
#endif

接着通过一小段代码来说明一下这个类的用法。

6
7
8
9
10
11
12
13
14
15
16
17
18
19
#if(CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID)
//typedefstructJniMethodInfo_
//{
//JNIEnv*env;
@H_674_46@ //jclassclassID;
//jmethodIDmethodID;
//}JniMethodInfo;
JniMethodInfoinfo;
//getStaticMethodInfo判断java定义的静态函数是否存在,返回bool
bool ret=JniHelper::getStaticMethodInfo(info, "org/cocos2dx/cpp/TestJni" ,monospace!important; font-size:1em!important; min-height:inherit!important; color:blue!important">"func1" "()V" );
if (ret)
{
log ( "callvoidfunc1()succeed" );
//传入类ID和方法ID,小心方法名写错,第一个字母是大写
info.env->CallStaticVoidMethod(info.classID,info.methodID);
}
大家书写代码的时候同样需要将代码使用条件编译写到里面,JniMethodInfo是一个结构体,这个结构体的定义就是代码中注释掉的地方,然后使用JniHelper调用了静态函数getStaticMethodInfo,从它的名字就知道这个函数的作用了,就是获得java层中静态函数的信息,这个信息保存在什么地方呢,当然是JniMethodInfo中了,我们要获取哪个类的哪个函数呢,第二个参数和第三个参数就是告诉JniHelper我们要获取的是哪个函数的信息了,第二个参数是类文件的包名路径,我在org/cocos2dx/cpp这个路径下新建了一个类,叫做TestJni。其实前面的路径就是一个包名,这里使用的时候用/代替.。org的路径当然就是我新建的这个工程的Android平台目录了。一会我要将这个项目打包然后测试一下,在eclipse下看看输出。第三个参数当然就是方法名字了,第四个参数是需要注意的一个,有人把它叫做签名,其实就是你要调用的java层函数的返回值和参数的类型说明。它把调用函数的参数写到前面的括号中,返回值跟在括号的后边,和我们平时书写函数的时候正好相反了。那那个V是什么东西呢,这个大写字母就是对应的一个类型,如果是void类型,那么就用一个V来代替,如果是一个int类型,那么就用一个I代替,是不是很简单,那其他的类型呢,如图所示。

放了两张表,用得时候查就好了,关于这个参数其他的细节问题待会讨论。整个函数的返回值是一个bool类型,什么意思不用说了吧。当这个函数的信息存在的时候我们就进入到了if中了,然后我使用了info结构体的第一个变量来调用了函数CallStaticVoidMethod,这个函数可真是需要说一说。

首先它的调用者就是保存函数信息的结构体JniMethodInfo的第一个成员变量env,这货是什么东西不用管,用就好了。

然后这个函数的第一个字母是大写,这一点要小心,Call后边如果跟Static代表的就是我要调用的是一个静态的函数,如果没有那就不是静态的,不是静态的函数,我们使用JniHelper获取信息的时候用得就是getMethodInfo这个函数。然后Void代表的是函数的返回值,来看我们的例子,我调用的函数func1是一个无参无返回值的函数,这个看什么地方,当然java代码我接着会向你展示,但是你可以直接看getStaticMethodInfo这个函数的第四个参数啊。这里的这个void代表的是函数的返回值类型,所以如果调用的是返回值为int的java函数,那就是CallStaticIntMethod了。里边的参数就是结构体info的第二个和第三个成员变量了,代表的是类ID和函数ID。这样的话基本的用法就说清楚了,接着就是TestJni中得代码了,我把要调用到得函数都写了出来。

19
20
21
22
23
24
25
26
27
28
29
30
31
32
packageorg.cocos2dx.cpp;
importandroid.util.Log;
@H_674_46@ public class TestJni
{
static void func1()
{
Log.e( "xiaota" "java:func1,calledsucceed!" );
}
static int func2()
{
return 3838438;
}
static Stringfunc3( i)
{
Stringstr= "geTintvalue:" +i;
:1.1em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,str);
str;
}
Stringfunc4(Stringstr)
{
:1.1em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,str);
str;
}
func5( a, b)
{
c=a+b;
"func5" );
c;
}
}

然后打包到Android平台,我们使用USB连接上电脑,打开eclipse,进行调试,看看信息输出了没有。

好了,这样的话就把这个流程都说明白了,下面我们看一些细节的地方。

32
33
34
35
36
37
38
39
40
@H_616_418@ 41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
@H_99_450@ 57
58
59
60
61
#if(CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID)
"androidplatform!" );
//typedefstructJniMethodInfo_
@H_674_46@ //{
//JNIEnv*env;
//jclassclassID;
//jmethodIDmethodID;
//}JniMethodInfo;
JniMethodInfoinfo;
//getStaticMethodInfo判断java定义的静态函数是否存在,返回bool
);
(ret)
);
//传入类ID和方法ID,小心方法名写错,第一个字母是大写
:1.1em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,info.methodID);
}
//调用的函数有返回值
"func2" "()I" );
(ret)
{
"callintfunc2()succeed" );
//返回的int值,用jint类型来接收
jintiret=info.env->CallStaticIntMethod(info.classID,info.methodID);
"func2的返回值是%d" :1.1em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,iret);
}
//调用的函数有参数有返回值,这里有坑,注意Ljava/lang/String;后边的;
"func3" "(I)Ljava/lang/String;" );
(ret)
{
"callintfunc3(int)succeed" );
//java层的类类型对应的是jobject,把需要传递的参数写到调用函数的后边
jobjectjobj=info.env->CallStaticObjectMethod(info.classID,info.methodID,1438);
}
@H_690_616@ @H_2_618@ //参数和返回值都是类类型
"func4" "(Ljava/lang/String;)Ljava/lang/String;" );
(ret)
{
"callStringfunc4(String)succeed" );
jobjectpara=info.env->NewStringUTF( "haha" );
jStringjstr=(jString)info.env->CallStaticObjectMethod(info.classID,para);
//使用jString2String函数将返回的jString类型的值转化为c++中的String类型
std::stringtext=JniHelper::JString2String(jstr);
"%s" :1.1em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,text.c_str());
}
@H_490_673@ @H_881_675@ //如果函数需要的参数是俩个或者是多个,可以采用如下的写法
"(II)I" );
(ret)
{
"callintfunc5(inta,intb)succeed" );
:1.1em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,1,2);
"returnvalueis%d" :1.1em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,iret);
}
上边的代码主要还是那俩个函数调用的说明,getStaticMethodInfo的第四个参数如果是类类型,注意要使用的签名,后边的分号也要加,如果参数有多个,直接连起来书写就可以了。使用CallStaticMethod调用的时候注意一下参数和返回值的类型,传递参数的时候直接写到函数的后边,但是参数类型要正确,返回值使用对应的类型来接受,这个类型就是前面加一个j,比如Java层返回的类型是int,那接受的类型就是jint,java层返回object,接受类型就是jobject。

以上是调用java的静态函数,接下来是非静态函数的调用。我将C++的代码和java的代码都贴出来。

17
JniMethodInfoinfo;
"org/cocos2dx/cpp/TestJniHelper" "getObj" "()Ljava/lang/Object;" );
//先获得类的对象,然后用这个对象去调用它的非静态函数
jobjectjobj;
@H_674_46@ (ret)
"callstaticmethod" );
jobj=info.env->CallStaticObjectMethod(info.classID,info.methodID);
}
//getMethodInfo判断java定义的类非静态函数是否存在,返回bool
re=JniHelper::getMethodInfo(info,monospace!important; font-size:1em!important; min-height:inherit!important; color:blue!important">"func" );
(rE)
{
"callno-staticmethod" //非静态函数调用的时候,需要的是对象,所以与静态函数调用的第一个参数不同
info.env->CallVoidMethod(jobj,info.methodID);
}
16
TestJniHelper
private TestJniHelperinstance= new TestJniHelper();
ObjectgetObj()
{
instance;
}
func()
"funciscalled" }
因为调用的是非静态的函数,所以我们使用CallVoidMethod的时候就不能传入类ID了,要传入一个对象,告诉它调用的是哪个对象的方法,所以为了有这么一个对象,我们就得先调用一个静态的方法来返回这个对象,然后用这个对象作为参数调用非静态函数。好了,关于Jni的基本用法就是这样了,只是本人的一点拙见,没有了解过的可以看看,如果是大神就绕路吧。


来源网址:http://www.cocos.com/doc/tutorial/show?id=1308

大佬总结

以上是大佬教程为你收集整理的Cocos2d-x利用jni调用java层代码全部内容,希望文章能够帮你解决Cocos2d-x利用jni调用java层代码所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。