本文附带几篇关于 C++ 与 Lua 交互方式的参考链接:

以下针对 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++ 对象上,从而实现双向调用。