cocos2d-x 发展到了3.0,发生了非常大的变化。脚本的绑定也由过去简单的tolua++生成为主,然后通过luafix修正传递回调,到现在更加智能的方式去做。
新的绑定方式简单来讲是分为三步:
使用llvm前端clang对c++代码进行分析,获取AST(抽象语法树)
利用预先写好的tolua代码作为模版,使用AST信息去填写模版
一些需要fix的回调,通过manual的方式进行包装(这样c++代码就不用专门提供脚本注册函数registerScript(int functionId)之类的接口),然后再回调到正确的lua函数。
优点:
缺点:
在$(EngineDir)/tools/tolua/目录下,执行genbindings.sh生成绑定代码,前提是你已经配置好环境,完成ini文件,如何编写以及配置,具体请看github上的文档,通常有误都是头文件目录错误,注意查看使用的是哪个版本的头文件。
新版本的回调函数绑定步骤如下:
第一、二步如下代码:
static int lua_cocos2dx_AssetsManager_setDelegate(lua_State* L)
{
if (nullptr == L)
return 0;
int argc = 0;
AssetsManager* self = nullptr;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
if (!tolua_isusertype(L,1,"AssetsManager",0,&tolua_err)) goto tolua_lerror;
#endif
self = (AssetsManager*) tolua_tousertype(L,1,0);
#if COCOS2D_DEBUG >= 1
if (nullptr == self)
{
tolua_error(L,"invalid ‘self‘ in function ‘lua_cocos2dx_AssetsManager_setDelegate‘\n", nullptr);
return 0;
}
#endif
argc = lua_gettop(L) - 1;
if (2 == argc)
{
#if COCOS2D_DEBUG >= 1
if (!toluafix_isfunction(L, 2, "LUA_FUNCTION", 0, &tolua_err) ||
!tolua_isnumber(L, 3, 0, &tolua_err) )
{
goto tolua_lerror;
}
#endif
LuaAssetsManagerDelegateProtocol* delegate = dynamic_cast<LuaAssetsManagerDelegateProtocol*>( self->getDelegate());
if (nullptr == delegate)
{
delegate = new LuaAssetsManagerDelegateProtocol();
if (nullptr == delegate)
return 0;
self->setUserObject(delegate);
self->setDelegate(delegate);
delegate->release();
}
LUA_FUNCTION handler = toluafix_ref_function(L, 2, 0);
ScriptHandlerMgr::HandlerType handlerType = (ScriptHandlerMgr::HandlerType) ((int)tolua_tonumber(L,3,0) + (int)ScriptHandlerMgr::HandlerType::ASSETSMANAGER_PROGRESS);
ScriptHandlerMgr::getInstance()->addObjectHandler((void*)delegate, handler, handlerType);
return 0;
}
CCLOG("‘setDelegate‘ function of AssetsManager has wrong number of arguments: %d, was expecting %d\n", argc, 2);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(L,"#ferror in function ‘setDelegate‘.",&tolua_err);
return 0;
#endif
}
第三步:
int LuaEngine::handleAssetsManagerEvent(ScriptHandlerMgr::HandlerType type,void* data)
{
if (nullptr == data)
return 0;
BasicScriptData* eventData = static_cast<BasicScriptData*>(data);
if (nullptr == eventData->nativeObject || nullptr == eventData->value)
return 0;
LuaAssetsManagerEventData* assetsManagerData = static_cast<LuaAssetsManagerEventData*>(eventData->value);
int handler = ScriptHandlerMgr::getInstance()->getObjectHandler((void*)eventData->nativeObject, type);
if (0 == handler)
return 0;
int ret = 0;
switch (type)
{
case ScriptHandlerMgr::HandlerType::ASSETSMANAGER_PROGRESS:
case ScriptHandlerMgr::HandlerType::ASSETSMANAGER_ERROR:
{
_stack->pushInt(assetsManagerData->value);
ret = _stack->executeFunctionByHandler(handler, 1);
}
break;
case ScriptHandlerMgr::HandlerType::ASSETSMANAGER_SUCCESS:
{
ret = _stack->executeFunctionByHandler(handler, 0);
}
break;
default:
break;
}
return ret;
}
第四步:
int LuaStack::executeFunctionByHandler(int nHandler, int numArgs)
{
int ret = 0;
if (pushFunctionByHandler(nHandler)) /* L: ... arg1 arg2 ... func */
{
if (numArgs > 0)
{
lua_insert(_state, -(numArgs + 1)); /* L: ... func arg1 arg2 ... */
}
ret = executeFunction(numArgs);
}
lua_settop(_state, 0
return ret;
}
原文:http://www.cnblogs.com/fonzieyang/p/3554889.html