Cocos2d-x Lua注册回调到C++

监听

_movementHandler = handler;         //缓存lua函数的引用 这个后边说

auto dispatcher = getCCEventDispatcher();

auto f = [this](cocos2d::EventCustom *event) //注册c代码形式的回调 这里用function做

{

auto eventData = (dragonBones::EventData*)(event->getUserData());

auto type = (int) eventData->getType();

auto movementId = eventData->animationState->name;

auto lastState = eventData->armature->getAnimation()->getLastAnimationState();

auto stack = cocos2d::LuaEngine::getInstance()->getLuaStack();

stack->pushObject(this, “db.ArmatureNode”);

扫描二维码关注公众号,回复: 11742605 查看本文章

stack->pushInt(type);

stack->pushString(movementId.c_str(), movementId.size());

//通过LuaStack调用lua里的函数    最后一个参数设置参数个数

stack->executeFunctionByHandler(_movementHandler, 3);

};

dispatcher->addCustomEventListener(dragonBones::EventData::COMPLETE, f);

}

void ArmatureNode::unregisterMovementEventHandler(void)

{

if (0 != _movementHandler)

{

cocos2d::LuaEngine::getInstance()->removeScriptHandler(_movementHandler); //移除lua函数的绑定

_movementHandler = 0;

}

}

提供Lua函数绑定到C的方法

上边的这个函数直接用cocos里的genbinding.py 是无法正确生成Lua里可调用的接口的,需要手动编写绑定方法.

说这个得用到Cocos2d-x中提供的一个方法:toluafix_ref_function会把一个Lua栈中的方法转成一个int,以便C++中调用。我会在最后面说这个

int tolua_db_DBCCArmature_registerMovementEventHandler(lua_State* tolua_S)

{

if (NULL == tolua_S)

return 0;

int argc = 0;

dragonBones::ArmatureNode* self = nullptr;

self = static_cast(tolua_tousertype(tolua_S,1,0)); //第一个参数 就是lua里的self

argc = lua_gettop(tolua_S) – 1;

if (1 == argc)

{

//第二个参数,就是Lua里的function 这里要通过toluafix_ref_function这个函数映射成一个Int值

int handler = (toluafix_ref_function(tolua_S,2,0));

self->registerMovementEventHandler(handler);

return 0;

}

return 0;

}

将绑定方法绑定到Lua环境里

int extends_ArmatureNode(lua_State* tolua_S)

{

lua_pushstring(tolua_S, “db.ArmatureNode”);//之前db.ArmatureNode是通过脚本绑定在lua里。这里只做扩展

lua_rawget(tolua_S, LUA_REGISTRYINDEX);

if (lua_istable(tolua_S,-1))

{

lua_pushstring(tolua_S,”registerMovementEventHandler”);

lua_pushcfunction(tolua_S,tolua_db_DBCCArmature_registerMovementEventHandler);

lua_rawset(tolua_S,-3);

}

lua_pop(tolua_S, 1);

return 0;

}

Lua里设置回调到C++

local arm = db.ArmatureNode:create(“Dragon”)

local animation = arm:getAnimation()

animation:gotoAndPlay(“walk”)

arm:registerMovementEventHandler(

function(…)

print(…)

end

)

测试

打印回调输出,测试通过 userdata 8 walk

其他

toluafix_ref_function 以及 toluafix_get_function_by_refid

这两个方法是相互对应的 toluafix_ref_function这个方法在注册表上将一个lua的function与一个function_id生成映射 toluafix_get_function_by_refid 方法可以通过前一个方法生成的function_id来讲绑定的lua function放到栈顶

//

TOLUA_API int toluafix_ref_function(lua_State* L, int lo, int def)

{

if (!lua_isfunction(L, lo)) return 0;

s_function_ref_id++;                            //function_id 加1

lua_pushstring(L, TOLUA_REFID_FUNCTION_MAPPING);//在注册表上,存放luafunction 映射table 的key压栈

lua_rawget(L, LUA_REGISTRYINDEX);               //获取方法映射表,放在栈顶

lua_pushinteger(L, s_function_ref_id);          //function_id压栈

lua_pushvalue(L, lo);                           //lo有效处索引处是lua方法,lua方法拷贝,压栈

lua_rawset(L, -3);                        //生成映射

lua_pop(L, 1);

return s_function_ref_id;

}

TOLUA_API void toluafix_get_function_by_refid(lua_State* L, int refid)

{

lua_pushstring(L, TOLUA_REFID_FUNCTION_MAPPING);            //存放luafunction 映射table 的key压栈

lua_rawget(L, LUA_REGISTRYINDEX);                           //获取方法映射表,放在栈顶

lua_pushinteger(L, refid);                                  //function_id压栈

lua_rawget(L, -2);                                          //获取到的luafunction 放到栈顶

lua_remove(L, -2);                                          //

}

executeFunctionByHandler

executeFunctionByHandler 这个方法只是通过toluafix_get_function_by_refid 获取到function然后通过lua_pcall 方法调用,代码就不写了。

猜你喜欢

转载自blog.csdn.net/qq_21743659/article/details/108616115