cocos2d-x 2.2.0 how to register a callback function in lua to C ++

Internal cocos2d-x used for tolua lua binding. But the engine does not provide a common interface so that we are able to register a function to lua C ++ level callback.
Look at the engine lua binding code, we were able to follow the method engines do.

Worth Tucao yes. This process is in development almost inevitable, and cocos2d-x does not actually use it as a common interface exposed to the developer, but I have to do it yourself. Really helpless.


The following simple message to a distribution class for the sample that demonstrates how to complete this work.

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;
}

Explanation

#include "CCLuaEngine.h"
This header from cocos2d-x\scripting\lua\cocos2dx_support
the entire contents of a folder in a package when cocos2d-x engine to make lua binding utility classes.
You need to join include search path to this folder in your project.

void registerScriptHandler(int nHandler)
This function needs to be exposed to lua.
Call this function in lua. Into a position to pass a parameter nHandler lua function, the integer handle value can be obtained in a C ++ nHandler side.
After assuming that no matter what time you want to call lua just registered callback function in C ++. The need to refer to an integer value that function.

void invokeLuaCallbackFunction(int msgId, const char* text)
In C ++ use this function is called, we expect it will call to the callback function defined in the lua.
Details of this function in the realization of what it meant, assuming you have some understanding of lua c api, then you should be able to understand very easy. I do not explain.

pkg file for the tolua

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

Use MessageDispatcher in the lua

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

Everything is all right.

。。。

Strange!

We have not found a pkg file type LUA_FUNCTION? ?
Yes, because of this parameter in lua should pass in a function, and to the C ++ side we get is an int.
This is not the default behavior tolua. But cocos2d-x for this situation to do a special deal.
Look tolua binding process cocos2d-x's. We can find content build.bat is this:
tolua++ -L basic.lua -o "../../scripting/lua/cocos2dx_support/LuaCocos2d.cpp" Cocos2d.pkg
here is some additional logic basic.lua, which type of logic processing LUA_FUNCTION also inside.

Then we can Zhaomaohuahu, please create such a lua file:

_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) == '\n'  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

Then when you run tolua ++ -L of this file as a parameter pass in on it.

You should really end of the story.



Guess you like

Origin www.cnblogs.com/ldxsuanfa/p/10959187.html