Cocos2d-x3.3RC0通过JNI实现Java与C++互调

Cocos2d-x3.3RC0通过JNI实现Java与C++互调,第1张

概述一、JNI JNI(Java Native Interface):Java的本地调用。本文通过JNI在Cocos2d-x3.3RC0中完成Java与C++的互调。具体实现以下两个功 能:(1)通过Android sdk的API得到应用程序的包名,并传递给C++层函数。(2)通过C++函数调用Android的Java层函数,显示一个对话框。点击按钮退出程序。 详细知识见:http://blog.cs 一、JNI
JNI(Java Native Interface):Java的本地调用。本文通过JNI在Cocos2d-x3.3RC0中完成Java与C++的互调。具体实现以下两个功
能:(1)通过AndroID sdk的API得到应用程序的包名,并传递给C++层函数。(2)通过C++函数调用AndroID的Java层函数,显示一个对话框。点击按钮退出程序。
详细知识见:http://blog.csdn.net/yuxikuo_1/article/details/39577257。其中最重要的是jnienv,这是一个C结构体。封装了许多
常用函数:具体如下:
struct _jnienv {/* do not rename this; it does not seem to be entirely opaque */const struct JNINativeInterface* functions;#if defined(__cplusplus)jint GetVersion(){ return functions->GetVersion(this); }jclass defineClass(const char *name,jobject loader,const jbyte* buf,Jsize bufLen){ return functions->defineClass(this,name,loader,buf,bufLen); }jclass FindClass(const char* name){ return functions->FindClass(this,name); }// 这里省略其他函数...}
Cocos2d-x对jni的 *** 作进行了封装,提供JniHelper类解决Java与C++的通信。
下面介绍两个常用的函数:
1、getStaticmethodInfo:

用来判断java类中静态函数是否存在,初始化结构体JniMethodInfo。该结构体封装了jnienv*和java.lang.class、函数ID。这样可以使用jnienv*调用CallStaticXXXMethod(jclass clazz,jmethodID methodID,...)和CallXXXMethod(jobject obj,jmethodID methodID,...)等常用函数,其中XXX代表函数返回值类型,如voID、int等。如下代码:参数1:JniMethodInfo,参数2:类的绝对路径,该路径为:proj.androID/src/下的目录,例如引擎模板工程下的路径为:src/org/cocos2dx/cpp/XXX。XXX为cpp下的java文件。记住路径中不用加.java后缀,因为路径使用的是类名。参数3:函数名,参数4:函数签名,具体规则见3类型签名

JniMethodInfo info;  bool ret = JniHelper::getStaticmethodInfo(info,"org/cocos2dx/cpp/AppActivity","getobj","()Ljava/lang/Object;");  jobject jobj;  if(ret)  {      log("call voID getobj() succeed");      jobj = info.env->CallStaticObjectMethod(info.classID,info.methodID);  }    bool re = JniHelper::getmethodInfo(info,"func1","()V");  if(re)  {      log("call func1 succeed");      info.env->CallVoIDMethod(jobj,info.methodID);  }  
2、getmethodInfo:用于调用java类的非静态函数
#if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)      JniMethodInfo info;      //判断org/cocos2dx/cpp/AppActivity.java中是否存在getobj静态函数      bool ret = JniHelper::getStaticmethodInfo(info,"()Ljava/lang/Object;");      jobject jobj;//用于存放返回的对象      if(ret)      {          log("call voID getobj() succeed");          jobj = info.env->CallStaticObjectMethod(info.classID,info.methodID);//调用getobj函数,返回一个对象      }      //判断org/cocos2dx/cpp/AppActivity.java中是否存在func1非静态函数      bool re = JniHelper::getmethodInfo(info,"()V");      if(re)      {          log("call func1 succeed");          info.env->CallVoIDMethod(jobj,info.methodID);//通过返回的对象调用非静态函数      }        #endif  

3、类型签名
类型签名 java类型
Z boolean
B byte
C char
S short
I int
J long
F float
D double
L full-qualifIEd-class; 完全限定的类
[ type type[ ]
(arg-types) ret-type 方法类型

如java方法:long f(int n,String s,int[] arr); 类型签名为:(ILjava/lang/String;[I)J。注意L后的分号,[是半开的,要与类型签名完全一致 二、具体步骤 1、创建Cocos2d-x3.3RC0工程
这个不做过多介绍,既然研究到Jni了,相比都不是太菜鸟了。
2、ADT与XCode分别导入工程 3、Xcode的Class目录下添加JniTest类
JniTest.h代码如下:JniTest.cpp暂时没有代码
#ifndef __JnIDemo__JniTest__#define __JnIDemo__JniTest__#include "cocos2d.h"USING_NS_CC;//定义两个C++方法,在Jni的test.h中被Java方法调用。//该方法被Java_org_cocos2dx_cpp_JniTestHelper_setPackagename调用//定义org/cocos2dx/cpp/JniTestHelper类中的setPackagename方法voID setPackagename(const char* packagename){    log("packagename = %s",packagename);}//该方法被Java_org_cocos2dx_cpp_JniTestHelper_exitApp调用//定义org/cocos2dx/cpp/JniTestHelper类中得exitApp函数voID exitApp(){    Director::getInstance()->end();}#endif /* defined(__JnIDemo__JniTest__) */

然后在HelloWorldScene.cpp中包含如下头文件,并在menuCloseCallback中添加如下代码:
//头文件包含,判断平台#if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)#include "../proj.androID/jni/hellocpp/test.h"//一定是相对路径#endif//调用C++调用Java层代码voID HelloWorld::menuCloseCallback(Ref* pSender){#if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)    showTipDialog("exit","Exit,Really Go?");#endif    #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)    exit(0);#endif}
4、Jni层代码
打开ADT工程目录下的jni/hellocpp/列表,在hellocpp下添加c++类,test.cpp和test.h。代码如下:一定包含extern "C"
</pre><p ><pre name="code" >#ifndef TEST_H_#define TEST_H_extern "C"{	//C++调Java的函数接口,该方法在HelloWorldScene中menuCallback函数中使用。	voID showTipDialog(const char* Title,const char* msg);}#endif

test.cpp代码如下:
#include "test.h"#include "cocos2d.h"#include "platform/androID/jni/JniHelper.h"#include "../../../Classes/JniTest.h"#include <jni.h>#define CLASS_name "org/cocos2dx/cpp/JniTestHelper"using namespace cocos2d;extern "C"{	//C++调Java的函数,在HelloWorldScene中的menuCallback函数中调用。	voID showTipDialog(const char* Title,const char* msg)	{		JniMethodInfo t;		//判断CLASS_name的类中是否存在showTipDialog函数,如果存在,则调用。		if(JniHelper::getStaticmethodInfo(t,CLASS_name,"showTipDialog","(Ljava/lang/String;Ljava/lang/String;)V"))		{			Jstring jTitle = t.env->NewStringUTF(Title);			Jstring jMsg   = t.env->NewStringUTF(msg);			t.env->CallStaticVoIDMethod(t.classID,t.methodID,jTitle,jMsg);			t.env->DeleteLocalRef(jTitle);			t.env->DeleteLocalRef(jMsg);		}	}	//Java调C++函数,Java函数来自org/cocos2dx/cpp/JniTestHelper的java类。同时该函数为JniTestHelper的java类中setPackagename原生方法的定义	voID Java_org_cocos2dx_cpp_JniTestHelper_setPackagename(jnienv* env,jobject thiz,Jstring packagename)	{		const char* pkgname = env->GetStringUTFChars(packagename,NulL);		setPackagename(pkgname);//此处调用的是Class目录下JniTest类中的函数		env->ReleaseStringUTFChars(packagename,pkgname);	}	//同上,该函数定义了JniTestHelper的java类中的exitApp原生函数。	voID Java_org_cocos2dx_cpp_JniTestHelper_exitApp(jnienv* env,jobject thiz)	{		exitApp();//此处调用的时Class目录中JniTest类中的函数。	}}
5、Java层函数
在ADT工程目录src/org.cocos2dx.cpp的目录下添加java类,JniTestHelper.java
1)JniTestHelper.java代码如下:
#include "test.h"#include "cocos2d.h"#include "platform/androID/jni/JniHelper.h"#include "../../../Classes/JniTest.h"#include <jni.h>#define CLASS_name "org/cocos2dx/cpp/JniTestHelper"using namespace cocos2d;extern "C"{	//C++调Java的函数,在HelloWorldScene中的menuCallback函数中调用。	voID showTipDialog(const char* Title,jobject thiz)	{		exitApp();//此处调用的时Class目录中JniTest类中的函数。	}}

2)AppActivity.java代码
package org.cocos2dx.cpp;import org.cocos2dx.lib.Cocos2dxActivity;import org.cocos2dx.lib.Cocos2dxGLSurfaceVIEw;import org.cocos2dx.lib.Cocos2dxHandler.DialogMessage;import androID.app.AlertDialog;import androID.content.DialogInterface;import androID.os.Bundle;import androID.os.Handler;import androID.os.Message;public class AppActivity extends Cocos2dxActivity{	public static final int SHOW_DIALOG = 0x0001;	protected voID onCreate(Bundle savedInstanceState)	{		super.onCreate(savedInstanceState);		JniTestHelper.init(mHandler);		//调用JniTestHelper的setPackagename函数,setPackagename函数在test.cpp中定义,最终调用C++层的setPackagename方法		JniTestHelper.setPackagename(this.getPackagename());	}		public Cocos2dxGLSurfaceVIEw onCreateVIEw(){		Cocos2dxGLSurfaceVIEw glSurfaceVIEw = new Cocos2dxGLSurfaceVIEw(this);		glSurfaceVIEw.setEGLConfigChooser(5,6,5,16,8);		return glSurfaceVIEw;	}	static {		System.loadlibrary("cocos2dcpp");	}		private Handler mHandler = new Handler()	{		public voID handleMessage(Message msg) {						switch (msg.what)			{			case SHOW_DIALOG:				DialogMessage dm = (DialogMessage)msg.obj;				new AlertDialog.Builder(AppActivity.this)				.setTitle(dm.titile)				.setMessage(dm.message).setNegativebutton("cancle",new DialogInterface.OnClickListener() {										@OverrIDe					public voID onClick(DialogInterface arg0,int arg1) {						// Todo auto-generated method stub						arg0.dismiss();					}				})				.setPositivebutton("Ok",new DialogInterface.OnClickListener(){					public voID onClick(DialogInterface arg0,int arg1) {						arg0.dismiss();						JniTestHelper.exitApp();//调用JniTestHelper的exitApp函数,exitApp函数在test.cpp中定义,最终调用C++层的exitApp方法					}				})				.create().show();				break;			}		}	};}



好了,代码和注释基本就结束了,还需要该的是AndroID.mk文件。代码如下:
LOCAL_SRC_fileS := hellocpp/main.cpp \				   hellocpp/test.cpp \   //将新建的test.cpp类加入mk文件                   ../../Classes/AppDelegate.cpp \                   ../../Classes/HelloWorldScene.cpp
之前介绍过万能mk文件生成方法,详见http://blog.csdn.net/yuxikuo_1/article/details/39552431。为了减少出问题的几率,建议改高AndroIDManifest中的SDK版本,不改无所谓也。
6、工程总目录
       
三、编译运行
如出现问题可参考 1)http://blog.csdn.net/yuxikuo_1/article/details/39654499 2)http://blog.csdn.net/yuxikuo_1/article/details/39552639 3)http://blog.csdn.net/yuxikuo_1/article/details/39671733
注:环境Mac XCode6 ADT22.2.1 Cocos2d-x3.3RC0 红米Note。

四、源码
说了这么多,没有源码那不是坑爹么。源码连接:http://pan.baIDu.com/s/1jGn80QE
总结

以上是内存溢出为你收集整理的Cocos2d-x3.3RC0通过JNI实现Java与C++互调全部内容,希望文章能够帮你解决Cocos2d-x3.3RC0通过JNI实现Java与C++互调所遇到的程序开发问题。

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1006441.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存