cocos2dx lua binding ,cocos2dx 绑定lua测试
前面2篇分别简单介绍
手动bind C++ 类和lua;http://blog.csdn.net/chenee543216/article/details/12074771
使用tolua++简化工作:http://blog.csdn.net/chenee543216/article/details/12172563
这篇简单聊聊 cocos2dx。
一、基本概念
所谓的lua绑定,其实目的就是导出C++的接口给lua,使得在lua中可以操作C++;
而lua和C/C++的唯一官方接口是stack。so,所谓的binding,就是C++,lua双方通过stack交换信息,然后对stack中信息进行解释,并执行相关动作的过程。
1 、
比如lua想生成一个dog 类,则在lua端: local d = Dog:creat(); 这个只是书面形式,其实lua解释器会自动填充stack。
比如,假设这个时候stack内容变成
"creat"
"Dog"
......... -- stack bottom
就是说,lua把2个标志入栈,一个是函数名,一个是类名;
在C/C++端,负责绑定的辅助代码(tolua++生成代码+libtolua++,或者我们第一篇文章中的LuaAnimal类)会根据 “Dog"生成一个类,并且根据某个表(见第一篇文章)去调用这个类中于”create“函数对应的函数。
OK,到这里,lua已经调用C、C++完成,并且生成相应的东西。
下面C/C++会把lua需要的返回值再压入stack。
lua端从stack中取出这个值,保留后面使用。
到这里一个完整过程over。
2、
lua端,再次调用 d:sound();
看官大概已经知道了。lua解释器会把相关信息压入stack,我们可以用第一篇中提供的函数stackDump()来展示stack内容。假设如下:
”sound"
"d"
在C++端,取出类实例地址 d,然后根据sound找对应类函数。比如sound00();然后调用d.sound00();
并且将相关返回值入栈,返回给lua。
3、用完以后gc,大家可以给Dog写个 Dog::~Dog()来看gc信息。
具体过程,给~Dog()下个断点,看C/C++ call stack即可。(我自己偷懒了~)
二、cocos2dx
1、
其实lua和cocos2dx木有啥关系,和cocos2dx sdk发生关系的是tolua++ 生成的C++代码而已。
lua是通过这个中间代码去操作cocos2dx的sdk的。
你实现一个功能,可能要写10几个class,还要调用native code,比如OC、或者java层代码。
但是一旦封装好以后,你使用这个功能只要一个简单调用而已。比如在C++端。我们调用 Money *m = Money::create();
我们最多只要用到几个public的函数,或者变量。并不关心private的函数和变量,和具体实现。
这个和tolua++的pkg文件编写规则一致。
再啰嗦一点:
比如上面Money类,我们只要 create,count 。。。 几个函数。那么tolua++生成的中间C++代码也只引用到这几个函数。
class MMM{
public:
int v00001;
int v00002;
....
int V99999;
void f00001();
void f00002()
.....
void f99999();
};
如果,我们在lua中只要调用v0001;和f00001;那么我们的tolua++的pkg只要包括
class MMM{
int v00001;
void f00001;
};
即可,大可不必管其它的东西。
2、cocos2dx自己的lua封装,可以到cocos2dx源码目录下面的tools/tolua++去看。
是官方提炼好的pkg,这些pkg最终都被include到Cocos2d.pkg,然后生成一个LuaCocos2d.cpp (见Makefile文件中描述)
这个LuaCocos2d.cpp就是整个cocos2dx中需要被lua使用的接口函数。
二、动手
我们自己写个练手
其实前面都已经写过了:见第二篇文章。唯一不同的是这里新的代码使用到cocos2dx sdk;
如下:
NativeHelper.h
#ifndef __NativeHelper_H__
#define __NativeHelper_H__ #include "cocos2d.h"
USING_NS_CC;
class NativeHelper : public cocos2d::CCLayer
{
public:
virtual bool init();
void openURL(std::string url,bool forceCheck=false); CREATE_FUNC(NativeHelper);
private: }; #endif
NativeHelper.cpp
#ifdef ANDROID
#include "NativeHelper.h"
#include <jni.h>
#include "platform/android/jni/JniHelper.h" bool NativeHelper::init()
{ return true;
} void NativeHelper::openURL(std::string url,bool forceCheck)
{
JniMethodInfo jmi;
if(JniHelper::getStaticMethodInfo(jmi , "org/cocos2dx/lib/Cocos2dxActivity" , "openUrl" , "([Ljava/lang/String;)V")){
jclass str_cls = jmi.env->FindClass("java/lang/String"); jstring str1 = jmi.env->NewStringUTF(url.c_str());
jstring str2 = jmi.env->NewStringUTF("Nothing ..."); jobjectArray arrs = jmi.env->NewObjectArray(2 , str_cls , 0);
jmi.env->SetObjectArrayElement(arrs , 0 , str1);
jmi.env->SetObjectArrayElement(arrs , 1 , str2);
jmi.env->CallStaticVoidMethod(jmi.classID , jmi.methodID , arrs); }
} #endif
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
#include "NativeHelper.h" bool NativeHelper::init()
{ return true;
} #define kTextFieldTagOfForumPassword 100 //====================================
//typedef void(^AlertBlock)(NSInteger); @interface BlockUIAlertView : UIAlertView
{
NSString *url;
}
//@property(nonatomic,copy)AlertBlock block;
@property(nonatomic,copy)NSString *url; - (id)initWithTitle:(NSString *)title
message:(NSString *)message
cancelButtonTitle:(NSString *)cancelButtonTitle
// clickButton:(AlertBlock)_block
otherButtonTitles:(NSString *)otherButtonTitles; //-(void)setURL:(NSString*)url; @end
@implementation BlockUIAlertView //@synthesize block;
@synthesize url; - (id)initWithTitle:(NSString *)title
message:(NSString *)message
cancelButtonTitle:(NSString *)cancelButtonTitle
// clickButton:(AlertBlock)_block
otherButtonTitles:(NSString *)otherButtonTitles { self = [super initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitles,nil]; // if (self) {
// self.block = _block;
// } return self;
} - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
// self.block(buttonIndex); if (buttonIndex == 1) {
CCLOG("------------button canceled");
return;
} UITextField *pwdTextField = (UITextField *)[alertView viewWithTag:kTextFieldTagOfForumPassword];
NSString *pwd = [pwdTextField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
CCLOG("--------------%s",[pwd UTF8String]); if ([pwd caseInsensitiveCompare:@"iamadult"] == NSOrderedSame) {
if ([url length]>[@"http://www.1.com" length]) {
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:url]];
}
} }
@end //====================================
void NativeHelper::openURL(std::string url,bool forceCheck)
{
if (!forceCheck) {
NSString * nsurl = [NSString stringWithCString:url.c_str()
encoding:[NSString defaultCStringEncoding]]; [[UIApplication sharedApplication]openURL:[NSURL URLWithString:nsurl]]; return;
} BlockUIAlertView *alertView = [[BlockUIAlertView alloc]
initWithTitle:@"请输入字符: iamadult"
message:@"\n\n"
cancelButtonTitle:@"确认"
// clickButton:^(NSInteger indexButton){
// if (indexButton == 0) {
// CCLOG("You press btn 0");
// }else if(indexButton == 1){
// CCLOG("You press btn 1");
// }
// }
otherButtonTitles:@"取消"]; [alertView setUrl:[NSString stringWithCString:url.c_str()
encoding:[NSString defaultCStringEncoding]]]; UITextField *textFieldPwd = [[UITextField alloc] initWithFrame:CGRectMake(27.0, 60.0, 230.0, 25.0)];
[textFieldPwd setBackgroundColor:[UIColor whiteColor]];
[textFieldPwd setTag:kTextFieldTagOfForumPassword];
[textFieldPwd setPlaceholder:@"请输入密码"];
[alertView addSubview:textFieldPwd];
[textFieldPwd release]; [alertView show];
[alertView release]; }
#endif
这3个文件实现一个NativeHelper类,这个类只干一件事:调用系统web浏览器打开一个URL。通过宏定义来控制android和ios的独立实现。(ios端和android端的区别是:ios端打开URL之前会弹出一个对话框,让用户输入验证字符。 just for parent protect )
我们调用方式简单如下:
NativeHelper *nhelper = NativeHelper::create();
const std::string strPrivacy = "http://http://blog.csdn.net/chenee543216/article/details/12172563";
nhelper->openURL(strPrivacy,true);
现在,我们把调用需要的2个函数用tolua++导出给lua,there are create() and openURL()
toluaNativeHelper.pkg
1
2 $#include "cocos2d.h"
3 $#include "NativeHelper.h"
4 class NativeHelper : public cocos2d::CCLayer
5 {
6 void openURL(std::string url,bool forceCheck=false);
7 static NativeHelper* create();
8 };
9
生成的命令为: tolua++ -o toluaNativeHelper.cpp toluaNativeHelper.pkg 生成如下cpp文件。
/*
** Lua binding: toluaNavieHelper
** Generated automatically by tolua++-1.0.92 on Mon Sep 30 16:21:12 2013.
*/ #ifndef __cplusplus
#include "stdlib.h"
#endif
#include "string.h" #include "tolua++.h" /* Exported function */
TOLUA_API int tolua_toluaNavieHelper_open (lua_State* tolua_S); #include "cocos2d.h"
#include "NativeHelper.h" /* function to register type */
static void tolua_reg_types (lua_State* tolua_S)
{
tolua_usertype(tolua_S,"NativeHelper");
tolua_usertype(tolua_S,"cocos2d::CCLayer");
} /* method: openURL of class NativeHelper */
#ifndef TOLUA_DISABLE_tolua_toluaNavieHelper_NativeHelper_openURL00
static int tolua_toluaNavieHelper_NativeHelper_openURL00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"NativeHelper",0,&tolua_err) ||
!tolua_iscppstring(tolua_S,2,0,&tolua_err) ||
!tolua_isboolean(tolua_S,3,1,&tolua_err) ||
!tolua_isnoobj(tolua_S,4,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
NativeHelper* self = (NativeHelper*) tolua_tousertype(tolua_S,1,0);
std::string url = ((std::string) tolua_tocppstring(tolua_S,2,0));
bool forceCheck = ((bool) tolua_toboolean(tolua_S,3,false));
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'openURL'", NULL);
#endif
{
self->openURL(url,forceCheck);
}
}
return 0;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'openURL'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE /* method: create of class NativeHelper */
#ifndef TOLUA_DISABLE_tolua_toluaNavieHelper_NativeHelper_create00
static int tolua_toluaNavieHelper_NativeHelper_create00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertable(tolua_S,1,"NativeHelper",0,&tolua_err) ||
!tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
{
NativeHelper* tolua_ret = (NativeHelper*) NativeHelper::create();
tolua_pushusertype(tolua_S,(void*)tolua_ret,"NativeHelper");
}
}
return 1;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'create'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE /* Open function */
TOLUA_API int tolua_toluaNavieHelper_open (lua_State* tolua_S)
{
tolua_open(tolua_S);
tolua_reg_types(tolua_S);
tolua_module(tolua_S,NULL,0);
tolua_beginmodule(tolua_S,NULL);
tolua_cclass(tolua_S,"NativeHelper","NativeHelper","cocos2d::CCLayer",NULL);
tolua_beginmodule(tolua_S,"NativeHelper");
tolua_function(tolua_S,"openURL",tolua_toluaNavieHelper_NativeHelper_openURL00);
tolua_function(tolua_S,"create",tolua_toluaNavieHelper_NativeHelper_create00);
tolua_endmodule(tolua_S);
tolua_endmodule(tolua_S);
return 1;
} #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501
TOLUA_API int luaopen_toluaNavieHelper (lua_State* tolua_S) {
return tolua_toluaNavieHelper_open(tolua_S);
};
#endif
自己添加到cocos2dx工程的class目录即可。
然后在
AppDelegate.cpp 中加入
文件开始部位:
extern int tolua_toluaNavieHelper_open (lua_State* tolua_S);
调用lua环境初始化之后
CCLuaEngine* pEngine = CCLuaEngine::defaultEngine();
CCScriptEngineManager::sharedManager()->setScriptEngine(pEngine);
tolua_toluaNavieHelper_open(pEngine->getLuaStack()->getLuaState());
ok;
现在你只要在lua文件中直接调用NativeHelper相关即可。如下
local nativehelper = NativeHelper:create()
nativehelper:openURL("http://www.sina.com",true)
写那那么多,也不知道说清楚了没有,有问题留言吧。
有错误,也欢迎留言指点。
参考:
http://blog.csdn.net/chenee543216/article/details/12172563
http://blog.csdn.net/chenee543216/article/details/12074771
http://www.himigame.com/lua-game/1259.html
http://blog.csdn.net/musicvs/article/details/8166655
tolua++官网各种文档
lua官网各种文档
cocos2dx lua binding ,cocos2dx 绑定lua测试的更多相关文章
- 【cocos2d-x + Lua(1) 绑定Lua并使用tolua++】
为什么要使用Lua进行游戏开发?转载请注明出处http://www.cnblogs.com/zisou/p/cocos2dx-lua1.html 上面一个问题我觉得在我们使用Lua之前需要深入思考的, ...
- 玩转cocos2d-x lua-binding, 实现c++与lua混合编程
引言 城市精灵GO(http://csjl.teamtop3.com/)是一款基于cocos2d-x开发的LBS社交游戏, 通过真实地图的探索, 发现和抓捕隐匿于身边的野生精灵, 利用游戏中丰富的玩法 ...
- 使用BabeLua3.x在cocos2d-x中编辑和调试Lua
BabeLua是一款基于VS2012/2013的Lua集成开发环境,具有Lua语法高亮,语法检查,自动补全,快速搜索,注入宿主程序内对Lua脚本进行调试,设置断点观察变量值,查看堆栈信息等功能. 如何 ...
- 使用BabeLua在cocos2d-x中编辑和调试Lua
使用BabeLua在cocos2d-x中编辑和调试Lua BabeLua是一款基于VS2012/2013的Lua集成开发环境,具有Lua语法高亮,语法检查.自己主动补全.高速搜索,注入宿主程序内对Lu ...
- Cocos2d-x JSB 自己主动绑定bindings
Javascript Binding (简称JSB) 自己主动绑定教程. Cocos2d-x JSB 自己主动绑定bindings-generator (以下简称B-G) 使用心得 假设想弄清深入原理 ...
- Unity3D热更新之LuaFramework篇[07]--怎么让unity对象绑定Lua脚本
前言 在上一篇文章 Unity3D热更新之LuaFramework篇[06]--Lua中是怎么实现脚本生命周期的 中,我分析了由LuaBehaviour来实现lua脚本生命周期的方法. 但在实际使用中 ...
- 【Cocos2d-x JavaScript Binding】
Cocos2d-x JavaScript Binding结合CocosBuilder跨平台游戏开发简明教程http://www.cocoachina.com/applenews/devnews/201 ...
- C++调用Lua编程环境搭建及测试代码示例
C++调用Lua编程环境搭建及测试代码示例 摘要:测试环境是VS2005+LuaForWindows_v5.1.4-45.exe+WIN7 1.安装lua开发环境LuaForWindows_v5.1. ...
- (转) Lua使用心得一 LUA和VC整合
这几天研究了一下lua,主要关注的是lua和vc之间的整合,把代码都写好放在VC宿主程序里,然后在lua里调用宿主程序的这些代码(或者叫接口.组件,随便你怎么叫),希望能用脚本来控制主程序的行为.这实 ...
随机推荐
- Codeforces 540D Bad Luck Island - 概率+记忆化搜索
[题意] 一个岛上有三种生物A,B,C,各有多少只在输入中会告诉你,每种最多100只 A与B碰面,A会吃掉B, B与C碰面,B会吃掉C, C与A碰面,C会吃掉A...忍不住想吐槽这种环形食物链 碰面是 ...
- zabbix图中出现中文乱码问题
我这周部署了zabbix监控服务器,但是配置过程中发现当有中文时,图中的中文会变成方块 如下图所示: 这个问题是由于zabbix的web端没有中文字库,我们最需要把中文字库加上即可 解决办法如下 1. ...
- ASP.NET MVC 几种 Filter 的执行过程源码解析
一.前言 之前也阅读过MVC的源码,并了解过各个模块的运行原理和执行过程,但都没有形成文章(所以也忘得特别快),总感觉分析源码是大神的工作,而且很多 人觉得平时根本不需要知道这些,会用就行了.其实阅读 ...
- ICOMOON!强悍的WEB字体图标制造器/Web字体使用实例
IcoMoon!一个可以通过个性化设置来创建自定义图标(字体)的生成器!也可以将SVG图片,转换成web字体 IcoMoon是一项免费的服务,通过使用不同设置使我们能够创建自定义的ICON图或ICON ...
- 什么是NSAssert?
断言, 判断是否符合某个特定条件, 符合就继续运行程序, 反之就抛出异常, 后面为自定义错误提示, 也可以使用NSParameterAssert, 在调试上有着很大的方便 int a = 0; NSA ...
- 日期Calendar/Date的用法
package cn.jason.datas; import java.util.Date;import java.text.ParseException;import java.text.Simpl ...
- 访问快递100的rest的请求
转:http://blog.csdn.net/u011115507/article/details/9172679 查快递的时候发现了一个http://www.kaidi100.com 是金蝶旗下的下 ...
- 解决java访问.netWebService的常见问题
到公司没多久,写了一个java调用.net写的webService结果期间用各种方法测试都没有完成,总是抛出异常,最后直接使用SOAP消息去进行调用才成功了,具体代码如下,仅供参考:import ja ...
- Direct2D 加载位图
说明: 通过WIC从文件加载位图. 可缩放后加载到内存. 源码: HRESULT LoadImageFormFile( IWICImagingFactory *pWicFactory, ID2D1Re ...
- jQuery中的模拟操作
jQuery中的模拟操作主要是通过trigger来触发,相当于页面加载完成后不需要用户点击按钮,就可以自动触发页面中的相关事件. trigger(type,[data])可以用来模拟触发自定义事件的触 ...