2011-10-18 32 views
2

在我們的菜單系統中,我們使用用於菜單組件事件回調的lua塊來定義xml菜單。目前,每次調用腳本回調函數時,都會調用lua_loadstring,這很慢。我試圖做到這一點,所以這隻會發生一次,當菜單加載。爲菜單系統實現lua回調

我最初的想法是保持每個菜單組件一個Lua表,並做到以下幾點到一個新的回調函數添加到表:

//create lua code that will assign a function to our table 
std::string callback = "temp." + callbackName + " = function (" + params + ")" + luaCode + "end"; 

//push table onto stack 
lua_rawgeti(L, LUA_REGISTRYINDEX, luaTableRef_); 

//pop table from stack and set it as value of global "temp" 
lua_setglobal(L, "temp"); 

//push new function onto stack 
int error = luaL_loadstring(L, callback.c_str()); 
if (error) 
{ 
    const char* errorMsg = lua_tostring(L, -1); 
    Dbg::Printf("error loading the script '%s' : %s\n", callbackName, errorMsg); 
    lua_pop(L,1); 
    return; 
} 

//call the lua code to insert the loaded function into the global temp table 
if (lua_pcall(L, 0, 0, 0)) 
{ 
    Dbg::Printf("luascript: error running the script '%s'\n", lua_tostring(L, -1)); 
    lua_pop(L, 1); 
} 

//table now has function in it 

這似乎有點髒。有沒有更好的方法,允許我直接從lua塊中將函數分配給表,而無需使用臨時全局變量並運行lua_pcall?

回答

3

如果你想把函數放在一個表中,那麼把函數放在表中。看起來你的Lua-stack-fu不強;考慮studying the manuala bit more closely

無論如何,我會說你最大的問題是你的堅持params。回調函數應該是可變的;他們以...作爲參數。如果他們想要得到這些值,就應該使用當地人是這樣的:

local param1, param2 = ...; 

但如果你堅持讓他們指定的參數列表,你可以做到以下幾點:

std::string luaChunk = 
    //The ; is here instead of a \n so that the line numbering 
    //won't be broken by the addition of this code. 
    "local " + params + " = ...; " + 
    luaCode; 

lua_checkstack(L, 3); 
lua_rawgeti(L, LUA_REGISTRYINDEX, luaTableRef_); 
if(lua_isnil(L, -1)) 
{ 
    //Create the table if it doesn't already exist. 
    lua_newtable(L); 

    //Put it in the registry. 
    lua_rawseti(L, LUA_REGISTRYINDEX, luaTableRef_); 

    //Get it back, since setting it popped it. 
    lua_rawgeti(L, LUA_REGISTRYINDEX, luaTableRef_); 
} 

//The table is on the stack. Now put the key on the stack. 
lua_pushlstring(L, callbackName.c_str(), callbackName.size()); 

//Load up our function. 
int error = luaL_loadbuffer(L, luaChunk.c_str(), luaChunk.size(), 
    callbackName.c_str()); 
if(error) 
{ 
    const char* errorMsg = lua_tostring(L, -1); 
    Dbg::Printf("error loading the script '%s' : %s\n", callbackName, errorMsg); 
    //Pop the function name and the table. 
    lua_pop(L, 2); 
    return; 
} 

//Put the function in the table. 
lua_settable(L, -3); 

//Remove the table from the stack. 
lua_pop(L, 1); 
+0

感謝清理起來。我會用「...」 – brunoma