实现菜单系统的Lua回调函数

在我们的菜单系统中,我们使用 xml 定义菜单,并使用 lua 代码块作为菜单组件事件的回调。目前,每次调用脚本回调时,我们都会调用相当慢的 lua_loadstring。我试图使它只发生一次,即加载菜单时只调用一次。

我的初始想法是针对每个菜单组件维护一个 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?

原文链接 https://stackoverflow.com/questions/7812801

点赞
stackoverflow用户734069
stackoverflow用户734069

如果你想把函数放在表中,那么就把函数放在表中。看起来你的 Lua-stack-fu 不太行,建议你仔细学习手册中的 内容

无论如何,我认为你的最大问题是对于 params 的坚持。回调函数应该是可变参数的;它们将 ... 作为参数。如果它们想要得到这些值,它们应该像这样使用本地变量:

local param1, param2 = ...;

但如果你坚持允许它们指定参数列表,你可以这样做:

std::string luaChunk =
    //这里有一个 ; 而不是 \n,因此代码的行号
    //不会因为代码的添加而被破坏。
    "local " + params + " = ...; " +
    luaCode;

lua_checkstack(L, 3);
lua_rawgeti(L, LUA_REGISTRYINDEX, luaTableRef_);
if(lua_isnil(L, -1))
{
    //如果表不存在,就创建它。
    lua_newtable(L);

    //将其放入注册表。
    lua_rawseti(L, LUA_REGISTRYINDEX, luaTableRef_);

    //获取它并将其弹出,因为设置它会将其弹出。
    lua_rawgeti(L, LUA_REGISTRYINDEX, luaTableRef_);
}

//这个表在栈上。现在把键放在栈上。
lua_pushlstring(L, callbackName.c_str(), callbackName.size());

//加载我们的函数。
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);
    //弹出函数名和表。
    lua_pop(L, 2);
    return;
}

//将函数放在表中。
lua_settable(L, -3);

//从栈中删除表。
lua_pop(L, 1);
2011-10-18 23:15:03