4

我知道与 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 调用?

4

2 回答 2

2

您需要Func1在尝试从返回的表(而不是全局表)中获取Func2原样之前调用。Func2Func1

然后您需要调用Func2并查找Table1该返回值等。

您收到什么“堆栈泄漏”投诉?如果您直接从 C 中调用此函数,那么是的,您需要确保在返回之前从 lua 堆栈中弹出您放在 lua 堆栈上的任何内容(不是供调用者使用等)。

于 2013-07-16T05:57:38.017 回答
0

GetNumber功能与您要使用的 lua 片段不完全相同。具体来说GetNumber,是"Func2"从注册表中获取 的值,而您的 lua 片段正在"Func2"从返回的表中获取 的值Func1()。除非您确定registry.Player.Func2==Func1().Func2始终为真,否则您的 C++ 版本将不会有相同的行为

让我们分解Func1():Func2().Table1.value1成更明确的步骤来帮助 C 翻译:

  1. 获取关联的函数_G.Func1
  2. 调用该函数并取回一个表
  3. "Func2"从步骤 2 中返回的表中获取关联的函数
  4. 调用该函数并将步骤 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了 lua 堆栈以它被发现的方式离开。如果您使用 C++,这可能可以通过 RAII 自动化。

于 2013-07-17T05:41:08.220 回答