cocos2d-x內部使用tolua進行lua綁定,可是引擎並無提供一個通用的接口讓咱們能夠把一個lua函數註冊給C++層面的回調事件。
翻看引擎的lua綁定代碼,咱們能夠仿照引擎中的方法來作。
值得吐槽的是,這套流程在開發中幾乎是不可避免的,而cocos2d-x居然不把它做爲一個公用接口暴露給開發者,而須要我本身動手,真是無奈。api
下面以一個簡單的消息分發類爲例子,演示如何完成這一工做。函數
class MessageDispather { public: static MessageDispather* sharedDispather(); public: void invokeLuaCallbackFunction(int msgId, const char* text); void registerScriptHandler(int nHandler); private: int mLuaHandlerId; };
#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-x\scripting\lua\cocos2dx_support
整個文件夾裏的內容是cocos2d-x引擎作lua綁定時封裝的一些工具類。
你須要在你的項目中添加這個目錄的include搜索路徑。工具
void registerScriptHandler(int nHandler)
這個函數須要暴露給lua。
在lua中調用這個函數,參數nHandler的位置傳進去一個lua函數,就可以在C++這邊獲得一個nHandler的整數句柄值。
以後任什麼時候間若是想要在C++中調用剛剛註冊的lua回調函數,須要以這個整數值來指代那個函數。post
void invokeLuaCallbackFunction(int msgId, const char* text)
在C++用調用此函數,咱們期待它會調用到一個在lua中定義的回調函數。
具體這個函數裏的實現是什麼意思,若是你對lua c api有必定了解的話應該很容易能看懂,我就再也不作解釋。ui
class MessageDispather { static MessageDispather* sharedDispather(); void registerScriptHandler(LUA_FUNCTION nHandler); };
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
那麼咱們能夠照貓畫虎,請建立這樣一個lua文件:spa
_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
而後在你執行tolua++的時候把這個文件做爲-L參數傳進去就能夠了。rest