如何在Lua C API中从函数获取多个返回值?

5

我希望知道如何在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

需要对代码进行调整以实现预期结果。

1
int ret1 = lua_tonumber(L, -1); should be int ret1 = lua_tonumber(L, -2); - user1810087
1
lua_tonumber不会从堆栈中弹出数值...我没有检查过,但我非常确定。因此,lua_tonumber(L,-2)和lua_tonumber(L,-1)应该可以解决问题。 - Gojita
注意:在堆栈上,除了问题之外,您还可以获得该特定调用的函数给出的任何结果。您必须使用结果数量根据需要清理堆栈,而不管是否知道如何处理它们。 - Tom Blodget
2个回答

6

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 。" Lua编程 : 25.2

2) "lua_pcall 在推入结果之前从堆栈中移除函数及其参数。" Lua编程 : 25.2


4

您正在两次使用同一索引:

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 -其他堆栈操作

[...] 函数lua_gettop返回堆栈中元素的数量,它也是最上面元素的索引。请注意,负索引-x等效于正索引gettop-x+1。 [...]

对于所有涉及堆栈访问的Lua函数(包括lua_tonumber),此负数索引定位方法都是有效的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接