cocos2dx v3.x C++绑定lua

本文转自:http://www.cocoachina.com/bbs/read.php?tid=200145 感谢作者分享。

嗳,侥天之幸初阶段游戏的 prototype 终于忽弄过去了!!!


这一个多月来使用 cocos2d-x 3.0 + lua 开发时踩中不少奇怪的雷,啧,也算是不作死就不会死的报应。

本该好好的用稳定的 2.2 版或是 quick-cocos2d-x,却总绕不过去想搞新玩意的念头,果真下场就如同老婆大人的名言:“你这就是该!”
好呗,废话不多说,单就这段时间碰上的问题与解决法子大致列举下,也许与先前发的、回的帖中有所重复,就请随意瞅着呗!
喔,还是多提一下,由于是台湾同胞,故,用词会有些不大一样,如有造成困扰,请多包涵。
--------------------------------------------------------------------------------
一、bindings-generator
当有一些感觉狂拽炫酷屌的 C or C++ 函数库想加到专案里时,难免会用上 cocos2d-x 自带的 bindings-generator 产出库让 lua 调用。
在 3.0 rc0 以前的说明并不像稳定版本这么“比较”多一些,花在 trial and error 上的时间也就相对的多了许多。过去的就说好不提了,单从现在稳定版的简单描述流程:
1.依照 bindings-generator 里 README.md 中下载并安装所会用上的工具,工具版本如果在 README 中有指定,麻烦请辛苦一些找到指定版本。要不,如果出了什么灵异现象,请不要怪罪这个工具怎么这么不科学……
2.参考tools/bindings-generator/test中的test.ini设定,为自己要产出的函数库量身订做变更设定内容。

3.如果函数库中有自订的 namespace(内地是称这个为啥?命名空间?!),请打开tools/bindings-generator/targets/lua/conversions.yaml,并在 ns_map 内容中补上自己的 namespace。要小心的是该内容仅吃空白字元,如果习惯用 TAB 来做缩排的请留意。

4.有需求的话就请变更 batch 档,可以让输出资料名称与路径指定到您想要的地方。当然,在 unix 环境下请变更 shell 档。

5.执行 batch 档!理论上来说应该就会看到一个 header 与 cpp 档,就可以拿来挂载了。

注意事项
1. bindings-generator 到 3.0 final 版本为止, 使用 c++11 的 functional 与 lambda function 用来做函数的参数或回传都是不行的 !并不是说执行输出的时候会错,而是会产生空的内容。
嗯,拿 cocos2d-x 自己的玩意来当例子:
在 EventDispatcher 类中有一个函数是这么被定义的:
EventListenerCustom* addCustomEventListener(const std::string &eventName,const std::function<void(EventCustom*)>& callback);

绑定 lua 绑定函数内容会输出到 lua_cocos2dx_auto.cpp 中,底下是实际的片段:
int lua_cocos2dx_EventDispatcher_addCustomEventListener(lua_State* tolua_S)
{
.... 太长了,省略之 ....

argc = lua_gettop(tolua_S)-1;
if (argc == 2)
{
std::string arg0;
std::function<void (cocos2d::EventCustom *)> arg1;

ok &= luaval_to_std_string(tolua_S,2,&arg0);

do {
// Lambda binding for lua is not supported.
assert(false);
} while(0)
;
if(!ok)
return 0;
cocos2d::EventListenerCustom* ret = cobj->addCustomEventListener(arg0,arg1);
object_to_luaval<cocos2d::EventListenerCustom>(tolua_S,"cc.EventListenerCustom",(cocos2d::EventListenerCustom*)ret);
return 1;
}
}
那一行 [Lambda binding for lua is not supported.] 内容整个亮了....QAQ
要是有非得使用 callback 函数不然会死的需求的话,还请改用 oldschool 的作法吧!
2. *.ini 设定档中每一个设定都是有他的特殊用意,请不要完全依样画葫芦式的全搬到自己函数库的设定里,请一定要适度的调整。
举个例子,在原先 test.ini 的最末:
# Determining whether to use script object(js object) to control the lifecycle of native(cpp) object or the other way around. Supported values are 'yes' or 'no'.
script_control_cpp =yes

在要挂载的函数库里有控制对象的生成与销毁的话麻烦这选项请填 no ,尤其是有写什么管理者来管理对象的更是要留意。
3. 请善用 conversions.yaml,这玩意儿是个好物!有自定义类要做 c to lua or lua to c 相互转换的话,可以利用这个来做。当然,要转换的函数还是要先行提供好才行,这部分属于比较进阶的玩意,但是用的好的话可以节省不少 handcode 的时间。
cocos2d-x 3.0rc0 - bindings-generator 问题与解决
这是先前针对 3.0 rc0 时所写的一点小吐槽,里头有简单的相关设定,烦请参考。
二、挂载自定义函式库
本来呢,以为将产生好的头文件与源码放到想摆放的位置,再参考 lua-tests 里如何挂载自定义函式库到 lua 就成了,但是……
天底下哪有这么便宜的事!
先看一下 AppDelegate.cpp 中的相关内容:
// register lua engine
LuaEngine* pEngine = LuaEngine::getInstance();
ScriptEngineManager::getInstance()->setScriptEngine(pEngine);

#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID ||CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
LuaStack* stack = pEngine->getLuaStack();
register_assetsmanager_test_sample(stack->getLuaState());
#endif
很单蠢,喔不,是看起来再单纯不过了咩。只要把那个 register_assetsmanager_test_sample( ) 替换成自订库产生出来的 register_all_ooxx_bindings( ) 不就行了?
可以试试,不过应该是程序崩溃才是。原因?让我们看下去……
嗯,底下问题解说的会有些生硬,如果只想看解决方法的话可直接跳过,毕竟不影响大局嘛。
问题:
LuaEngine 被初始时会建立起 LuaStack 对象,而真正 lua 栈对象 luaStack 的建立、挂载 cocos2d-x 自己的 modules、读入一些外部库(如 luasock、lsqlite)这些行为都是在 被建立起时一并完成的。
流程大概是这样:
LuaEngine::getInstance() → new LuaEngine → LuaEngine::init() → LuaStack::create() → LuaStack::init()

可以打开 CCLuaStack.cpp 瞧一下,位置约莫在 cocos/scripting/lua-bindings/manual/ 底下,看一下 LuaStack::init() 函数,就会明白上头再说些什么东西来着。
话说回来,这怎么会造成挂载自己库时程序崩溃呢?
为了处理 2.x <-> 3.0 之间转换的问题,在 LuaEngine::init() 时执行了三个 .lua:
bool LuaEngine::init(void)
{
_stack = LuaStack::create();
_stack->retain();
executeScriptFile("DeprecatedEnum.lua");
executeScriptFile("DeprecatedClass.lua");
executeScriptFile("Deprecated.lua");

return true;
}
问题就出在执行 executeScriptFile() 后,为了让 lua 的栈能够被正常的再使用,执行完后都会将 lua 栈归零。
int LuaEngine::executeScriptFile(const char* filename)
{
int ret = _stack->executeScriptFile(filename);
_stack->clean();// 这里会归零,就是很简单的调用 lua_settop(_state,0)
return ret;
}
归零并不是错误的!问题点是在处理完后要挂载自己输出库的时间点,摆个简单转换后要挂载的函数的内容看一下:
TOLUA_API int register_all_ooxx_bindings(lua_State* tolua_S)
{
tolua_open(tolua_S);
tolua_module(tolua_S,"ooxx",0);
tolua_beginmodule(tolua_S,"ooxx");
lua_register_ooxx_bindings_TalkComponent(tolua_S);
tolua_endmodule(tolua_S);
return 1;
}
如果什么事都不处理,按照前文提到的仿照 lua-test 一样把自己的库挂上去:
// register lua engine
LuaEngine* pEngine = LuaEngine::getInstance();
ScriptEngineManager::getInstance()->setScriptEngine(pEngine);
LuaStack* stack = pEngine->getLuaStack();
register_all_ooxx_bindings(stack->getLuaState());
执行之……就会发现死在 tolua_module( ) !一般而言,应该都是死在 里的 lua_rawget(L,-2)
TOLUA_API void tolua_module (lua_State* L,const char* name,int hasvar)
{
if (name)
{
/* tolua module */
lua_pushstring(L,name);
lua_rawget(L,-2);// <- 会死在这里!
if (!lua_istable(L,-1))/* check if module already exists */
为什么?
熟悉 lua c API 的看后应该就知道问题点。 想去取得 -2 index 的栈值,但此时栈内仅有一个字串,其他完全是空的,不死才是不科学!
整个整理一下,会挂掉的原因出于执行了三个标记已过时便于转换用的 .lua chunk file ,然后 lua 栈被归零,最后要挂载自订库,然后……就没有再然后了……
解决:
有两个方法可以解决。
一个是先前随便乱回答的偷机方法:打开 LuaEngine.cpp,把那三行执行 .lua 的注解掉,最后把执行那三个 .lua 的移到挂载完自己的函数库后再执行就成了。
传送门,请按
详细可看上头连结,虽然写得有些啰唆……
第二个法子单纯点,既然栈是空的那就给他资料不就得了:
auto engine = LuaEngine::getInstance();
ScriptEngineManager::getInstance()->setScriptEngine(engine);
auto luaStack = engine->getLuaStack()->getLuaState();
if (luaStack)
{
lua_getglobal(luaStack,"_G");
register_all_ooxx_bindings(luaStack);
lua_settop(luaStack,0);
}
就这样,简单吧 :)
--------------------------------------------------------------------------------
写的好像太繁琐了……本来想一口气把这段时间 cocos2d-x 3.0 + lua 遇上的问题与解决方法都写出来的,没想到居然花了一个多小时才写这么一点。
呃,今天的就是个 part 1,等明后天有闲暇时补上其余部分。
以上!
Ps. 站内代码高亮到底要怎么使用啊……T___T

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


    本文实践自 RayWenderlich、Ali Hafizji 的文章《How To Create Dynamic Textures with CCRenderTexture in Cocos2D 2.X》,文中使用Cocos2D,我在这里使用Cocos2D-x 2.1.4进行学习和移植。在这篇文章,将会学习到如何创建实时纹理、如何用Gimp创建无缝拼接纹
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@163.com微信公众号:HopToad 欢迎转载,转载标注出处:http://blog.csdn.netotbaron/article/details/424343991.  软件准备 下载地址:http://cn.cocos2d-x.org/download 2.  简介2.1         引用C
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从Cocos2D-x官网上下载,进入网页http://www.cocos2d-x.org/download,点击Cocos2d-x以下的Download  v3.0,保存到自定义的文件夹2:从python官网上下载。进入网页https://www.python.org/downloads/,我当前下载的是3.4.0(当前最新
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发引擎,易学易用,支持多种智能移动平台。官网地址:http://cocos2d-x.org/当前版本:2.0    有很多的学习资料,在这里我只做为自己的笔记记录下来,错误之处还请指出。在VisualStudio2008平台的编译:1.下载当前稳
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《最强大脑》娱乐节目。将2048改造成一款挑战玩家对数字记忆的小游戏。邮箱:appdevzw@163.com微信公众号:HopToadAPK下载地址:http://download.csdn.net/detailotbaron/8446223源码下载地址:http://download.csdn.net/
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试以QtCreatorIDE来进行CMake构建。Cocos2d-x3.X地址:https://github.com/cocos2d/cocos2d-x1.打开QtCreator,菜单栏→"打开文件或项目...",打开cocos2d-x目录下的CMakeLists.txt文件;2.弹出CMake向导,如下图所示:设置
 下载地址:链接:https://pan.baidu.com/s/1IkQsMU6NoERAAQLcCUMcXQ提取码:p1pb下载完成后,解压进入build目录使用vs2013打开工程设置平台工具集,打开设置界面设置: 点击开始编译等待编译结束编译成功在build文件下会出现一个新文件夹Debug.win32,里面就是编译
分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net前言上次用象棋演示了cocos2dx的基本用法,但是对cocos2dx并没有作深入的讨论,这次以超级马里奥的源代码为线索,我们一起来学习超级马里奥的实
1. 圆形音量button事实上作者的本意应该是叫做“电位计button”。可是我觉得它和我们的圆形音量button非常像,所以就这么叫它吧~先看效果:好了,不多解释,本篇到此为止。(旁白: 噗。就这样结束了?)啊才怪~我们来看看代码:[cpp] viewplaincopyprint?CCContro
原文链接:http://www.cnblogs.com/physwf/archive/2013/04/26/3043912.html为了进一步深入学习贯彻Cocos2d,我们将自己写一个场景类,但我们不会走的太远,凡是都要循序渐进,哪怕只前进一点点,那也至少是前进了,总比贪多嚼不烂一头雾水的好。在上一节中我们建
2019独角兽企业重金招聘Python工程师标准>>>cocos2d2.0之后加入了一种九宫格的实现,主要作用是用来拉伸图片,这样的好处在于保留图片四个角不变形的同时,对图片中间部分进行拉伸,来满足一些控件的自适应(PS: 比如包括按钮,对话框,最直观的形象就是ios里的短信气泡了),这就要求图
原文链接:http://www.cnblogs.com/linji/p/3599478.html1.环境和工具准备Win7VS2010/2012,至于2008v2版本之后似乎就不支持了。 2.安装pythonv.2.0版本之前是用vs模板创建工程的,到vs2.2之后就改用python创建了。到python官网下载版本2.7.5的,然后
环境:ubuntu14.04adt-bundle-linux-x86_64android-ndk-r9d-linux-x86_64cocos2d-x-3.0正式版apache-ant1.9.3python2.7(ubuntu自带)加入环境变量exportANDROID_SDK_ROOT=/home/yangming/adt-bundle-linux/sdkexportPATH=${PATH}:/$ANDROID_SDK_ROOTools/export
1开发背景游戏程序设计涉及了学科中的各个方面,鉴于目的在于学习与进步,本游戏《FlappyBird》采用了两个不同的开发方式来开发本款游戏,一类直接采用win32底层API来实现,另一类采用当前火热的cocos2d-x游戏引擎来开发本游戏。2需求分析2.1数据分析本项目要开发的是一款游
原文链接:http://www.cnblogs.com/linji/p/3599912.html//纯色色块控件(锚点默认左下角)CCLayerColor*ccc=CCLayerColor::create(ccc4(255,0,0,128),200,100);//渐变色块控件CCLayerGradient*ccc=CCLayerGradient::create(ccc4(255,0,0,
原文链接:http://www.cnblogs.com/linji/p/3599488.html//载入一张图片CCSprite*leftDoor=CCSprite::create("loading/door.png");leftDoor->setAnchorPoint(ccp(1,0.5));//设置锚点为右边中心点leftDoor->setPosition(ccp(240,160));/
为了答谢广大学员对智捷课堂以及关老师的支持,现购买51CTO学院关老师的Cocos2d-x课程之一可以送智捷课堂编写图书一本(专题可以送3本)。一、Cocos2d-x课程列表:1、Cocos2d-x入门与提高视频教程__Part22、Cocos2d-x数据持久化与网络通信__Part33、Cocos2d-x架构设计与性能优化内存优
Spawn让多个action同时执行。Spawn有多种不同的create方法,最终都调用了createWithTwoActions(FiniteTimeAction*action1,FiniteTimeAction*action2)方法。createWithTwoActions调用initWithTwoActions方法:对两个action变量初始化:_one=action1;_two=action2;如果两个a
需要环境:php,luajit.昨天在cygwin上安装php和luajit环境,这真特么是一个坑。建议不要用虚拟环境安装打包环境,否则可能会出现各种莫名问题。折腾了一下午,最终将环境转向linux。其中,luajit的安装脚本已经在quick-cocos2d-x-develop/bin/中,直接luajit_install.sh即可。我的lin
v3.0相对v2.2来说,最引人注意的。应该是对触摸层级的优化。和lambda回调函数的引入(嗯嗯,不枉我改了那么多类名。话说,每次cocos2dx大更新。总要改掉一堆类名函数名)。这些特性应该有不少人研究了,所以今天说点跟图片有关的东西。v3.0在载入图片方面也有了非常大改变,仅仅只是