Cocos2d-x 3.0 中的lua binding - fonzieyang

39 篇文章 0 订阅

http://www.tuicool.com/articles/zQRbia

Cocos2d-x 3.0 中的lua binding

How it work

cocos2d-x 发展到了3.0,发生了非常大的变化。脚本的绑定也由过去简单的tolua++生成为主,然后通过luafix修正传递回调,到现在更加智能的方式去做。

新的绑定方式简单来讲是分为三步:

  1. 使用llvm前端clang对c++代码进行分析,获取AST(抽象语法树)
  2. 利用预先写好的tolua代码作为模版,使用AST信息去填写模版
  3. 一些需要fix的回调,通过manual的方式进行包装(这样c++代码就不用专门提供脚本注册函数registerScript(int functionId)之类的接口),然后再回调到正确的lua函数。

优点:

  • 一套c++多套统绑定
  • 脚本系统透明化,c++代码不必提供脚本接口

缺点:

  • 熟悉tolua++的同学需要重新学习
  • 回调显得稍微麻烦一些,难以自动化绑定,每次需要绑定回调都要自己写c++代码

生成绑定

在$(EngineDir)/tools/tolua/目录下,执行genbindings.sh生成绑定代码,前提是你已经配置好环境,完成ini文件,如何编写以及配置,具体请看github上的文档 ,通常有误都是头文件目录错误,注意查看使用的是哪个版本的头文件。

扩展绑定

新版本的回调函数绑定步骤如下:

  1. 增加函数对目标回调接口传递lua function
  2. 在该回调lua_CFunction里面,把lua function注册到事件管理器,同时增加自己的事件类型
  3. 在目标触发回调的地方,派发事件,传递自己的数据
  4. 把数据传递到注册起来的函数中

第一、二步如下代码:

  1. static int lua_cocos2dx_AssetsManager_setDelegate(lua_State* L)
  2. {
  3. if (nullptr == L)
  4. return 0;

  5. int argc = 0;
  6. AssetsManager* self = nullptr;

  7. #if COCOS2D_DEBUG >= 1
  8. tolua_Error tolua_err;
  9. if (!tolua_isusertype(L,1,"AssetsManager",0,&tolua_err))goto tolua_lerror;
  10. #endif

  11. self = (AssetsManager*) tolua_tousertype(L,1,0);

  12. #if COCOS2D_DEBUG >= 1
  13. if (nullptr == self)
  14. {
  15. tolua_error(L,"invalid 'self' in function 'lua_cocos2dx_AssetsManager_setDelegate'\n", nullptr);
  16. return 0;
  17. }
  18. #endif

  19. argc = lua_gettop(L) - 1;

  20. if (2 == argc)
  21. {
  22. #if COCOS2D_DEBUG >= 1
  23. if (!toluafix_isfunction(L, 2,"LUA_FUNCTION", 0, &tolua_err) ||
  24. !tolua_isnumber(L, 3, 0, &tolua_err) )
  25. {
  26. goto tolua_lerror;
  27. }
  28. #endif
  29. LuaAssetsManagerDelegateProtocol* delegate = dynamic_cast<LuaAssetsManagerDelegateProtocol*>( self->getDelegate());
  30. if (nullptr == delegate)
  31. {
  32. delegate = new LuaAssetsManagerDelegateProtocol();
  33. if (nullptr == delegate)
  34. return 0;

  35. self->setUserObject(delegate);
  36. self->setDelegate(delegate);
  37. delegate->release();
  38. }

  39. LUA_FUNCTION handler = toluafix_ref_function(L, 2, 0);
  40. ScriptHandlerMgr::HandlerType handlerType = (ScriptHandlerMgr::HandlerType) ((int)tolua_tonumber(L,3,0) + (int)ScriptHandlerMgr::HandlerType::ASSETSMANAGER_PROGRESS);

  41. ScriptHandlerMgr::getInstance()->addObjectHandler((void*)delegate, handler, handlerType);
  42. return 0;
  43. }

  44. CCLOG("'setDelegate' function of AssetsManager has wrong number of arguments: %d, was expecting %d\n", argc, 2);
  45. return 0;

  46. #if COCOS2D_DEBUG >= 1
  47. tolua_lerror:
  48. tolua_error(L,"#ferror in function 'setDelegate'.",&tolua_err);
  49. return 0;
  50. #endif
  51. }

第三步:

  1. int LuaEngine::handleAssetsManagerEvent(ScriptHandlerMgr::HandlerType type,void* data)
  2. {
  3. if (nullptr == data)
  4. return 0;

  5. BasicScriptData* eventData = static_cast<BasicScriptData*>(data);
  6. if (nullptr == eventData->nativeObject ||nullptr == eventData->value)
  7. return 0;

  8. LuaAssetsManagerEventData* assetsManagerData = static_cast<LuaAssetsManagerEventData*>(eventData->value);

  9. int handler = ScriptHandlerMgr::getInstance()->getObjectHandler((void*)eventData->nativeObject, type);

  10. if (0 == handler)
  11. return 0;

  12. int ret = 0;
  13. switch (type)
  14. {
  15. case ScriptHandlerMgr::HandlerType::ASSETSMANAGER_PROGRESS:
  16. case ScriptHandlerMgr::HandlerType::ASSETSMANAGER_ERROR:
  17. {
  18. _stack->pushInt(assetsManagerData->value);
  19. ret = _stack->executeFunctionByHandler(handler,1);
  20. }
  21. break;

  22. case ScriptHandlerMgr::HandlerType::ASSETSMANAGER_SUCCESS:
  23. {
  24. ret = _stack->executeFunctionByHandler(handler,0);
  25. }
  26. break;

  27. default:
  28. break;
  29. }

  30. return ret;
  31. }

第四步:

  1. int LuaStack::executeFunctionByHandler(int nHandler,int numArgs)
  2. {
  3. int ret = 0;
  4. if (pushFunctionByHandler(nHandler))/* L: ... arg1 arg2 ... func */
  5. {
  6. if (numArgs > 0)
  7. {
  8. lua_insert(_state, -(numArgs + 1));/* L: ... func arg1 arg2 ... */
  9. }
  10. ret = executeFunction(numArgs);
  11. }
  12. lua_settop(_state, 0
  13. return ret;
  14. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值