Реализация обратных вызовов lua для системы меню - PullRequest
2 голосов
/ 18 октября 2011

В нашей системе меню мы определяем меню в формате 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-чанка, не используя глобальную переменную temp и не запуская lua_pcall?

1 Ответ

3 голосов
/ 19 октября 2011

Если вы хотите поместить функцию в таблицу, поместите функцию в таблицу.Кажется, твое Lua-stack-fu не сильно;рассмотрим изучение руководства чуть более подробно .

В любом случае, я бы сказал, что самая большая проблема, с которой вы столкнулись, это ваше требование 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...