本文附带几篇关于 C++ 与 Lua 交互方式的参考链接:
- https://my.oschina.net/kkkkkkkkkkkkk/blog/825686
- https://my.oschina.net/kkkkkkkkkkkkk/blog/518154
- https://my.oschina.net/kkkkkkkkkkkkk/blog/746684
以下针对 cocos2dx 的具体实现进行说明。
1. Scheduler::update 中派发 Lua 事件
在 Scheduler::update 里直接遍历 Lua 层注册的事件并逐一派发:
#if CC_ENABLE_SCRIPT_BINDING
//
// Script callbacks
//
// Iterate over all the script callbacks
if (!_scriptHandlerEntries.empty())
{
for (auto i = _scriptHandlerEntries.size() - 1; i >= 0; i--)
{
SchedulerScriptHandlerEntry* eachEntry = _scriptHandlerEntries.at(i);
if (eachEntry->isMarkedForDeletion())
{
_scriptHandlerEntries.erase(i);
}
else if (!eachEntry->isPaused())
{
eachEntry->getTimer()->update(dt);
}
}
}
#endif
2. Node 中的事件派发
Node 类通过成员变量持有脚本 handler,并在 update 方法中将事件消息派发到 Lua:
成员变量
#if CC_ENABLE_SCRIPT_BINDING
int _scriptHandler; ///< script handler for onEnter() & onExit(), used in Javascript binding and Lua binding.
int _updateScriptHandler; ///< script handler for update() callback per frame, which is invoked from lua & javascript.
ccScriptType _scriptType; ///< type of script binding, lua or javascript
#endif
// override me
void Node::update(float fDelta)
{
#if CC_ENABLE_SCRIPT_BINDING
if (0 != _updateScriptHandler)
{//派发事件消息到lua
//only lua use
SchedulerScriptData data(_updateScriptHandler,fDelta);
ScriptEvent event(kScheduleEvent,&data);
ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&event);
}
#endif
if (_componentContainer && !_componentContainer->isEmpty())
{
_componentContainer->visit(fDelta);
}
}
除上述方式外,cocos2dx 还提供了许多其他事件派发手段。整体思路是通过 ScriptEngine 派发事件——大部分 C++ 类都通过 toLua 导出到 Lua,导出类会自动将 Lua 的 handle 通过 ScriptHandlerMgr::getInstance()->addObjectHandler 接口绑定到 C++ 对象上,从而实现双向调用。