Как вызвать функцию lua из другой функции lua?

Я пишу расширение lua (5.1) для нашего приложения, которое позволяет нашим клиентам расширять его с помощью дополнительных экранов без нашей поддержки.

В целом это работает очень хорошо, а с помощью дюжины оберток даже очень удобно, но теперь я получил следующую ситуацию:

У меня есть два объекта пользовательских данных, объект Timer и объект Window.
Пользователь может «прикреплять» к ним события, просто определяя их члены OnTimer и OnSizeChanged.

Это все еще работает очень хорошо:
mainLoop (C ++) -> проверить все таймеры (C ++) -> объект сценария присоединен? (C ++), затем:

// get ud by reference / stack: +1 / 1
lua_rawgeti(mState, LUA_REGISTRYINDEX, miReferenceId);
lua_getfenv(mState, -1); // get attached table / +1 / 2 total
lua_getfield(mState, -1, functionName.ToChar()); // +1 / 3 total
if (!lua_isfunction(mState, -1))
{
...
}
lua_remove(mState, -2); // remove table / -1 / 2 total
lua_remove(mState, -2); // remove ud / -1 / 1 total, just function remaining
// ( .. user data still pushed at this point ..)
lua_pcall(mState, 1, 0, 0);

Таким образом, в следующем сценарии все по-прежнему отлично (сложите 0, прежде чем инициировать вызов и после):

function OnTimer(Self)
Log("Some text") // Log calls C++ luaLog with 1 argument
end

myTimer = timer.new()
myTimer.OnTimer=OnTimer;

Если скрипт lua выглядит так:

timer = timer.new()
window = window.new()

function OnTimer(Self)
window:SetSize(323.5,234.5)
end

function OnSizeChanged(Self,NewWidth,NewHeight)
Log("Sized changed")
end

timer.OnTimer = OnTimer
window.OnSizeChanged = OnSizeChanged

Тогда callstack в C ++ будет:

timer::HandleTimer (C++) ->
push "OnTimer"  function ->
push timer ud ->
pcall (L,1) -> .. (Lua)
static int luaChangeSize(lua_State *L) (back to C++) ->
Window::SetSize ->
The window sees "oooooooh, an event handler has been assigned" ->
push "OnSizeChanged" function, window ud, x, y ->
pcall(L,3,0,0) -> .. (Lua) ->
int luaLog(lua_state* L) (back to C++ again)

Конечно, в точке, где OnSizeChanged должен быть вызван, стек все еще содержит содержимое предыдущего обратного вызова luaChangeSize и не является пустым.

Я думал, что мог бы просто очистить стек, вытолкнув все аргументы luaChangeSize перед вызовом Window :: SetSize и восстановив их впоследствии, но это не работает. Результат является немного случайным в зависимости от созвездия стека вызовов, от «не могу вызвать номер» до случайного повторного вызова предыдущей функции в стеке. (gettop определенно равен 0 до и после всех вызовов).

Итак: Как я могу «сделать резервную копию» текущего стека и впоследствии восстановить его, как это делает сам lua в созвездии C ++ -> Lua -> C ++?

Большое спасибо.

2

Решение

Концепция резервного копирования и восстановления стека кажется неправильной. Разве вы не можете просто оставить стек таким, какой он есть, и позволить новому вызову работать поверх существующего стека. Убедитесь, что все обращается к элементам в стеке, используя относительный к верхнему индексу, а не абсолютный.

2

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector