cocos2d c++与java的交互

       接触这么长时间的cocos2d了,虽说是跨平台的,但是一直没有机会去了解c++跟平台语言交互(java,oc),看到许多网上的不是很详细,就抽空整理下,如有不足欢迎指出。今天就简单写下c++跟java的交互,他们之间是通过一个叫jni的东西是实现的,不知道是什么鬼的,请自行百度下。

我们实现的就是在c++层上点击事件,将信息传递到android的java层,然后java层再将信息返回给c++层。


我们先看下c++层,我们就以大家熟悉的HelloWorld为例:

#include "HelloWorldScene.h"
USING_NS_CC;
#if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "../proj.android/jni/hellocpp/test.h"
#endif
Scene* HelloWorld::createScene()
{
    auto scene = Scene::create();
    auto layer = HelloWorld::create();
    layer->setName("HelloWorldScene");
    scene->addChild(layer);
    return scene;
}
bool HelloWorld::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
	Size visibleSize = Director::getInstance()->getVisibleSize();
	Vec2 origin = Director::getInstance()->getVisibleOrigin();
    auto closeItem = MenuItemImage::create("CloseNormal.png","CloseSelected.png",CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
    closeItem->setScale(4,4);
	closeItem->setPosition(1000,300);
    auto menu = Menu::create(closeItem, NULL);
    menu->setPosition(Vec2::ZERO);
    this->addChild(menu, 1);

    return true;
}

void HelloWorld::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
	MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
    return;
#endif
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
	{
		showTipDialog("Hi,Bruce","Have you received the message?");
	}
#endif

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}
void HelloWorld::createMessage(const char *str)
{
	auto label = Label::createWithTTF(str, "fonts/Marker Felt.ttf", 24);
	label->setScale(4);
	label->setPosition(1000,800);
	this->addChild(label, 1);
}

效果图如上,我们通过点击中间的按钮将两个字符串通过jni中的Test类中的showTipDialog方法,传递给java层

Test.h代码如下:

#ifndef TEST_H
#define TEST_H

extern "C"
{
void showTipDialog(const char *title, const char *msg);
}
#endif
Test.cpp代码如下:

#define CLASS_NAME "org/cocos2dx.cpp/JniTestHelper"
#include "cocos2d.h"
using namespace cocos2d;
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#include "../../../Classes/JniTest.h"

extern "C"
{
	void showTipDialog(const char *title, const char *msg)
	{
		JniMethodInfo t;
		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);
		}
	}

	void Java_org_cocos2dx_cpp_AppActivity_returnMessage(JNIEnv *env, jobject thiz, jstring packageName)
	{
		char* rtn = NULL;
		jclass clsstring = env->FindClass("java/lang/String");
		jstring strencode = env->NewStringUTF("utf-8");
		jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
		jbyteArray barr= (jbyteArray)env->CallObjectMethod(packageName, mid, strencode);
		jsize alen = env->GetArrayLength(barr);
		jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
		if (alen > 0)
		{
		rtn = (char*)malloc(alen + 1);
		memcpy(rtn, ba, alen);
		rtn[alen] = 0;
		}
		env->ReleaseByteArrayElements(barr, ba, 0);
		log("222222====%s",rtn);
		showMessage(rtn);
	}
}
首先我们看下Test.cpp中的showTipDialog方法,
JniHelper::getStaticMethodInfo(t, CLASS_NAME, "showTipDialog", "(Ljava/lang/String;Ljava/lang/String;)V")
CLASS_NAME这个就是要调用的类路径了,在上边通过宏定义的,showTipDialog当然就是类方法了,

"(Ljava/lang/String;Ljava/lang/String;)V" 这个就是表明该函数是无返回值的并且带有两个string参数的函数。

t.env->CallStaticVoidMethod(t.classID, t.methodID, jTitle, jMsg); 这个就是调用静态函数,类ID,方法ID,跟要传递的参数,第一个参数要是调用CallVoidMethod是不用传的。通过这些就会调用我们java层JniTestHelper类的静态方法

showTipDialog,下面我们看下java层代码:

JniTestHelper.java

package org.cocos2dx.cpp;

import org.cocos2dx.cpp.AppActivity;

import android.os.Message;
import android.os.Handler;

public class JniTestHelper {
	
	private static Handler mHandler;
	private static void showTipDialog(final String title, final String text)
    {
    	DialogMessage dm = new DialogMessage();
    	dm.title = title;
    	dm.msg = text;
    	System.out.println("111111===="+dm.title+" "+dm.msg);  
    	AppActivity.returnMessage("Yes,I have received the message ! ! !");
    }
}
通过System.out.println("111111===="+dm.title+" "+dm.msg);   我们就能将我们在HelloWorld中传过来的字符串打印了 Hi,Bruce,Have you received the message?,因为主要是说下c++与java的互相调用,所以,就顺便再通过
JniTestHelper调用jni中的returnMessage 函数,将Yes,I have received the message ! ! ! 传递给HelloWorld了,这个

returnMessage我们首先应在AppActivity中声明下public static native void returnMessage(String packageName);

然后我们就可以在jni中实现这个函数了,但是函数名命名必须为下:

Java_org_cocos2dx_cpp_AppActivity_returnMessage

这个函数,在上边Test中已经贴出来了,这里就不重复了,主要说下这个函数的命名,

Java:这个不用说;

org_cocos2dx_cpp:包名;

AppActivity:类名

returnMessage:函数名

在实现的过程中,其中有个jstring类型的字符串,我们需要转换下,不然会因为类型不一致出现乱码,在转码的过程中又用到了jni调用的java层,如果不是因为转码,这个转码过程可以忽略了。然后通过showMessage就到了我们HelloWorld了

我们看下showMessage的实现:

JniTest.h

//  Created by Bruce on 16-3-27.

#ifndef __JniDemo__JniTest__
#define __JniDemo__JniTest__

#include "cocos2d.h"
USING_NS_CC;
#include "HelloWorldScene.h"

void showMessage(const char* packageName)
{
     auto helloLayer = (HelloWorld*)Director::getInstance()->getRunningScene()->getChildByName("HelloWorldScene");
     helloLayer->createMessage(packageName);
}

#endif /* defined(__JniDemo__JniTest__) */
这样我们就调到了HelloWorld中的createMessage方法中。


最终我们就成功的将从java层中传递过来的信息显示出来了。

代码下载地址:http://pan.baidu.com/s/1gfkPOIn

2017年03月27日 23:50 

                                                                                                                                                        写于苏州












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值