Я знаю основы взаимодействия с lua и C, и в настоящее время я пытаюсь выполнить следующую строку lua в c ++
Func1():Func2().Table1.value1
Я пытаюсь получить значение «value2» и использовать его в моей C-программе. Ниже приведен код, который я написал, чтобы попытаться получить это значение в C.
int GetNumber()
{
int retn = 0;
g_clientlua.lua_getfield(LUA_REGISTRYINDEX, "Player");
g_clientlua.lua_getfield(-1, "Func2");
g_clientlua.lua_getfield(LUA_GLOBALSINDEX, "Func1");
g_clientlua.lua_call(0, 1);
g_clientlua.lua_call(1, 1);
if (g_clientlua.lua_isnil(-1))
return retn;
g_clientlua.lua_getfield(-1, "Table1");
if (g_clientlua.lua_isnil(-1))
return retn;
g_clientlua.lua_getfield(-1, "value1");
if (g_clientlua.lua_isnil(-1))
return retn;
retn = (int)g_clientlua.lua_tointeger(-1);
}
Объект clientlua — это объект, который в основном позволяет мне вызывать метод, который вызывает его эквивалент функции lua_ * и заполняет параметр указателя lua_state переменной-членом, которая является указателем на состояние lua.
Каждый раз, когда я называю это, он жалуется на то, что я вызываю утечку из стека lua. Чтобы решить эту проблему, я попытался добавить lua_pop(3)
до конца, но потом просто вылетает моя программа без сообщения об ошибке, поэтому я предполагаю, что делаю что-то не так.
У кого-нибудь есть слова мудрости для меня? Какая-то потеряна здесь. Я сомневаюсь, что вышеупомянутый код даже написан правильно, как бы я написал вышеупомянутый вызов lua в C?
Вам нужно позвонить Func1
прежде чем пытаться получить Func2
как Func2
исходит из таблицы, которая Func1
возвращает (а не из глобальной таблицы).
Тогда вам нужно позвонить Func2
и посмотреть Table1
в этом возвращаемом значении и т. д.
Какую жалобу на «утечку стека» вы получаете? Если вы вызываете эту функцию непосредственно из C, тогда да, вы должны быть уверены, что все, что вы положили в стек lua (не для потребления вызывающей стороной и т. Д.), Извлечено из стека lua, прежде чем вы вернетесь.
GetNumber
функция выполняет не то же самое, что фрагмент кода lua, который вы собираетесь использовать. конкретно GetNumber
получает значение "Func2"
из реестра, в то время как ваш фрагмент Lua получает значение "Func2"
из таблицы, возвращенной Func1()
, Если вы не уверены, что registry.Player.Func2
== Func1().Func2
является всегда правда, ваша версия C ++ не будет иметь такого же поведения.
Давай сломаться Func1():Func2().Table1.value1
в более явные шаги, чтобы помочь с переводом C:
_G.Func1
"Func2"
из возвращенной таблицы в шаге 2Я обнаружил, что полезно отслеживать, что стек содержит в качестве побочного комментария при выполнении операций:
int GetNumber()
{
// Func1()
gclientlua.lua_getfield(LUA_GLOBALSINDEX, "Func1"); // Func1
g_clientlua.lua_call(0, 1); // {}
// Func2( {} )
g_clientlua.lua_getfield(-1, "Func2"); // {}, Func2
g_clientlua.lua_insert(-2); // Func2, {}
g_clientlua.lua_call(1, 1); // {}
if( g_clientlua.lua_type(-1) != LUA_TTABLE )
{
g_clientlua.lua_pop(1);
return 0;
}
// {}.Table1
g_clientlua.lua_getfield(-1, "Table1"); // {}, {}(Table1)
if( g_clientlua.lua_type(-1) != LUA_TTABLE )
{
g_clientlua.lua_pop(2);
return 0;
}
// tonumber( Table1.value1 )
g_clientlua.lua_getfield(-1, "value1"); // {}, {}(Table1), value1
int retn = g_clientlua.lua_tointeger(-1);
g_clientlua.lua_pop(3);
return retn;
}
Заметить, что GetNumber
выскакивает все аргументы, которые он помещает в стек перед возвратом. Это гарантирует, что GetNumber
выходит из стека луа так, как он был найден. Вероятно, это можно автоматизировать с помощью RAII, если вы используете C ++.