zoukankan      html  css  js  c++  java
  • cocos2d-x 2.2.0 怎样在lua中注冊回调函数给C++

    cocos2d-x内部使用tolua进行lua绑定。可是引擎并没有提供一个通用的接口让我们能够把一个lua函数注冊给C++层面的回调事件。
    翻看引擎的lua绑定代码,我们能够仿照引擎中的方法来做。


    值得吐槽的是。这套流程在开发中差点儿是不可避免的,而cocos2d-x居然不把它作为一个公用接口暴露给开发人员,而须要我自己动手,真是无奈。


    以下以一个简单的消息分发类为样例,演示怎样完毕这一工作。

    MessageDispatcher.h

    class MessageDispather
    {
    public:
        static MessageDispather* sharedDispather();
    
    public:
        void invokeLuaCallbackFunction(int msgId, const char* text);
        void registerScriptHandler(int nHandler);
    
    private:
        int mLuaHandlerId;
    };


    MessageDispatcher.cpp

    #include "CCLuaEngine.h"
    
    MessageDispather* sharedDispather()
    {
        static MessageDispather* instance = NULL;
        if(instance == NULL) instance = new MessageDispather();
        return instance;
    }
    
    void MessageDispather::invokeLuaCallbackFunction(int msgId, const char* text)
    {
        if(mScriptHandler > 0)
        {
            CCLuaStack* stack = CCLuaEngine::defaultEngine()->getLuaStack();
            stack->pushInt(msgId);
            stack->pushString(text);
            stack->executeFunctionByHandler(mScriptHandler, 2);
            stack->clean();
        }
    }
    
    void MessageDispather::registerScriptHandler(int nHandler)
    {
        mLuaHandlerId = nHandler;
    }

    说明

    #include "CCLuaEngine.h"
    这个头文件来自cocos2d-xscriptingluacocos2dx_support
    整个目录里的内容是cocos2d-x引擎做lua绑定时封装的一些工具类。
    你须要在你的项目中加入这个文件夹的include搜索路径。

    void registerScriptHandler(int nHandler)
    这个函数须要暴露给lua。
    在lua中调用这个函数。參数nHandler的位置传进去一个lua函数。就行在C++这边得到一个nHandler的整数句柄值。
    之后不论什么时间假设想要在C++中调用刚刚注冊的lua回调函数,须要以这个整数值来指代那个函数。

    void invokeLuaCallbackFunction(int msgId, const char* text)
    在C++用调用此函数,我们期待它会调用到一个在lua中定义的回调函数。
    详细这个函数里的实现是什么意思,假设你对lua c api有一定了解的话应该非常easy能看懂,我就不再做解释。

    用于tolua的pkg文件

    class MessageDispather
    {
        static MessageDispather* sharedDispather();
        void registerScriptHandler(LUA_FUNCTION nHandler);
    };

    在lua中使用MessageDispatcher

    local function onMessage(msgId, text)
        print(msgId, text)
    end
    MessageDispatcher:sharedDispatcher():registerScriptHandler(onMessage)

    万事大吉。。。。。才怪!

    有没有发现我们的pkg文件里有一个类型是LUA_FUNCTION??
    对,由于这个參数在lua中应该传入一个函数。而到了C++这边我们拿到的却是一个int。
    这并非tolua的缺省行为,而是cocos2d-x针对这样的情况做的一个特殊处理。
    翻看cocos2d-x的tolua绑定流程,我们能够发现build.bat中的内容是这种:
    tolua++ -L basic.lua -o "../../scripting/lua/cocos2dx_support/LuaCocos2d.cpp" Cocos2d.pkg
    这里basic.lua是一些额外的逻辑,当中处理LUA_FUNCTION类型的逻辑也在里面。

    那么我们能够照猫画虎,请创建这样一个lua文件:

    _is_functions = _is_functions or {}
    _to_functions = _to_functions or {}
    
    -- register LUA_FUNCTION, LUA_TABLE, LUA_HANDLE type
    _to_functions["LUA_FUNCTION"] = "toluafix_ref_function"
    _is_functions["LUA_FUNCTION"] = "toluafix_isfunction"
    _to_functions["LUA_TABLE"] = "toluafix_totable"
    _is_functions["LUA_TABLE"] = "toluafix_istable"
    
    local toWrite = {}
    local currentString = ''
    local out
    local WRITE, OUTPUT = write, output
    
    function output(s)
        out = _OUTPUT
        output = OUTPUT -- restore
        output(s)
    end
    
    function write(a)
        if out == _OUTPUT then
            currentString = currentString .. a
            if string.sub(currentString,-1) == '
    '  then
                toWrite[#toWrite+1] = currentString
                currentString = ''
            end
        else
            WRITE(a)
        end
    end
    
    function post_output_hook(package)
        local result = table.concat(toWrite)
        local function replace(pattern, replacement)
            local k = 0
            local nxt, currentString = 1, ''
            repeat
                local s, e = string.find(result, pattern, nxt, true)
                if e then
                    currentString = currentString .. string.sub(result, nxt, s-1) .. replacement
                    nxt = e + 1
                    k = k + 1
                end
            until not e
            result = currentString..string.sub(result, nxt)
            if k == 0 then print('Pattern not replaced', pattern) end
        end
    
        replace([[*((LUA_FUNCTION*)]], [[(]])
        replace([[tolua_usertype(tolua_S,"LUA_FUNCTION");]], [[]])
    
        WRITE(result)
    end

    然后在你运行tolua++的时候把这个文件作为-L參数传进去就能够了。

    应该真的万事大吉了。



  • 相关阅读:
    C#中virtual 方法和abstract方法的区别
    解决zabbix的cannot allocate shared memory of size错误
    批量改名的shell脚本
    /bin/bash和/bin/sh的区别
    搭建redmine全攻略——与apache整合(CentOS 5.8 64位)
    内网监控利器——Nagios
    Maven
    TypeScript
    ShardingSphere
    Spring框架源码分析
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7049716.html
Copyright © 2011-2022 走看看