【问题标题】:How to get multiple return values from function in Lua C API?如何从 Lua C API 中的函数获取多个返回值?
【发布时间】:2019-08-23 17:45:38
【问题描述】:

我想知道如何从 Lua C API 中的函数获取多个返回值。

Lua 代码:

function test(a, b)
  return a, b -- I would like to get these values in C++
end

C++ 代码:(调用函数的部分)

/* push functions and arguments */
lua_getglobal(L, "test");  /* function to be called */
lua_pushnumber(L, 3);   /* push 1st argument */
lua_pushnumber(L, 4);   /* push 2nd argument */

/* call the function in Lua (2 arguments, 2 return) */
if (lua_pcall(L, 2, 2, 0) != 0)
{
    printf(L, "error: %s\n", lua_tostring(L, -1));
    return;
}
int ret1 = lua_tonumber(L, -1);
int ret2 = lua_tonumber(L, -1);
printf(L, "returned: %d %d\n", ret1, ret2);

我得到的结果:

返回:4 4

我期望的结果:

返回:3 4

【问题讨论】:

  • int ret1 = lua_tonumber(L, -1); 应该是int ret1 = lua_tonumber(L, -2);
  • lua_tonumber 不会从堆栈中弹出值...我不检查但我很确定。所以也许 lua_tonumber(L,-2) 和 lua_tonumber(L,-1) 应该可以解决问题
  • 注意:除了问题之外,在堆栈上,您已经获得了该函数为该特定调用为您提供的任何结果。您必须根据需要使用number of results 来清理堆栈,无论如何处理它们。

标签: c++ c lua


【解决方案1】:

lua_tonumber 不会改变lua_State 的堆栈。您需要在两个不同的索引处阅读它1

int ret1 = lua_tonumber(L, -2);
int ret2 = lua_tonumber(L, -1);
printf(L, "returned: %d %d\n", ret1, ret2);

在您调用test 之前,您的堆栈如下所示:

lua_getglobal(L, "test");  /* function to be called */
lua_pushnumber(L, 3);   /* push 1st argument */
lua_pushnumber(L, 4);   /* push 2nd argument */

|     4     |  <--- 2
+-----------+
|     3     |  <--- 1
+-----------+
|    test   |  <--- 0
+===========+

调用后2

lua_pcall(L, 2, 2, 0) 

+-----------+
|     3     |  <--- -1
+-----------+
|     4     |  <--- -2
+===========+

另一种方法是在阅读后手动弹出结果:

int ret1 = lua_tonumber(L, -1);
lua_pop(L, 1);
int ret2 = lua_tonumber(L, -1);
lua_pop(L, 1);
printf(L, "returned: %d %d\n", ret1, ret2);

1) "如果一个函数返回多个结果,首先推送第一个结果;所以,如果有n结果,第一个结果将在索引-n最后一个在索引-1。” Programming in Lua : 25.2

2) "在推送结果之前,lua_pcall 从堆栈中删除函数及其参数。" Programming in Lua : 25.2

【讨论】:

    【解决方案2】:

    你使用相同的索引两次:

    int ret1 = lua_tonumber(L, -1);
    int ret2 = lua_tonumber(L, -1);
    

    堆栈是这样填充的:

    -- Lua
    return a, b
    
    +---+
    | b | <-- top ("relative" index -1)
    +---+
    | a | <-- -2
    +---+
    

    所以你的 C++ 代码应该是:

    // I don't know what ret1 or ret2 suppose to be.
    // 1 = first on stack, or first return value?
    // renamed to a and b for consistency with lua return a,b
    int b = lua_tonumber(L, -1);
    int a = lua_tonumber(L, -2);
    // lua_pop(L, 2); // don't forget to pop the values
    

    来自24.2.3 – Other Stack Operations

    [...]lua_gettop函数返回栈中元素的个数,也是栈顶元素的索引。 请注意,负索引 -x 等价于正索引 gettop - x + 1。 [...]

    这种负索引定位对所有关于堆栈访问的 Lua 函数都有效,包括 lua_tonumber。

    【讨论】:

      猜你喜欢
      • 2018-11-24
      • 1970-01-01
      • 2012-09-30
      • 2018-12-06
      • 2017-09-11
      • 2021-12-13
      • 2011-04-04
      • 2016-09-27
      • 2021-12-21
      相关资源
      最近更新 更多