我知道与lua和C交互的基础知识,我目前正在尝试在c ++中执行以下lua行
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)
,但是它只是在没有报告错误的情况下崩溃我的程序,所以我认为我做错了。
任何人对我都有任何智慧的话语?有点失去了这里。我怀疑上面的代码是否写得正确,如何在C中编写上述lua调用?
答案 0 :(得分:2)
在尝试获取Func1
之前需要调用Func2
,因为Func2
来自Func1
返回的表(而不是来自全局表)。
然后,您需要致电Func2
并在该返回值中查找Table1
等。
你得到什么“堆栈泄漏”投诉?如果你直接从C调用这个函数然后是的话,你需要确保在返回之前从lua堆栈中弹出任何你放在lua堆栈上的东西(不是由调用者消费等)。 / p>
答案 1 :(得分:0)
GetNumber
功能与您要使用的lua代码段完全不同。具体来说,GetNumber
从注册表中获取"Func2"
的值,而您的lua代码段从"Func2"
返回的表中获取Func1()
的值。除非您确定registry.Player.Func2
== Func1().Func2
总是为真,否则您的C ++版本将不会有相同的行为。
让我们将Func1():Func2().Table1.value1
分解为更明确的步骤来帮助进行C翻译:
_G.Func1
"Func2"
相关联的功能我发现在执行操作时跟踪堆栈包含的内容是有帮助的:
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
以找到它的方式离开lua堆栈。如果您正在使用C ++,这可以通过RAII自动完成。