我有这个功能:

static int generic_pcall_wrapper(lua_State* L, int (*funct)(lua_State*)){
    int narg = lua_gettop(L);
    lua_pushcfunction(L, funct);
    lua_rotate(L, 1, 1);

    int res = lua_pcall(L, narg, LUA_MULTRET, 0);
    if(res != 0){
        //handle error
    }
    return ??; // I would like to return 1 as in sum()
}

static int sum(lua_State* L){
    int a = lua_tointeger(L, -1);
    int b = lua_tointeger(L, -2);    
    lua_pop(L, 1);   
    lua_pushnumber(L, a + b);
    return 1;
}

static int foo(lua_State* L){
    return generic_pcall_wrapper(L, sum);
}

我想让Generic_pcall_wrapper()返回sum()返回的值.

请注意,此函数应该接受许多不同的函数,并且它们如何处理返回值未指定,唯一可靠的值是每个函数返回的数字.

推荐答案

我不太明白的第一件事是,为什么求和函数需要lua_pop.这个对lua_op的调用非常不寻常,在the official examples中不存在.

static int sum(lua_State* L)
{
  int a = lua_tointeger(L, -1);
  int b = lua_tointeger(L, -2);    
  lua_pop(L, 1); /* unusual, probably not needed */
  lua_pushnumber(L, a + b);
  return 1;
}

关于原始问题,在回调sum中,返回值表示已将多少结果压入堆栈.该值由Lua运行时使用,Lua API的用户不可用.因此,如果API用户稍后需要该值,则需要使用Lua函数保存该值.

使用Lua API,一种自然的方法是将其推送到堆栈上.

static int sum(lua_State* L)
{
  int a = lua_tointeger(L, -1);
  int b = lua_tointeger(L, -2);
  lua_pushnumber(L, a + b); /* push the result of sum          */
  lua_pushinteger(L, 1);    /* sum return 1 value on the stack */
  return 2; /* return all the values (sum) and then #values */
}

然后:

  1. 泛型包装获取堆栈上的返回值的数量
  2. 包装器从堆栈中删除该特定值
  3. 返回给调用方的值的个数
static int generic_pcall_wrapper(lua_State* L, int (*funct)(lua_State*))
{
  int narg = lua_gettop(L);
  lua_pushcfunction(L, funct);

  //push argument again, but above the function
  int stack_size = lua_gettop(L);
  
  for (int i = 1; i < stack_size; i++)
    lua_pushvalue(L, i);
    
  int res = lua_pcall(L, narg, LUA_MULTRET, 0);

  /* Get the number of values which have been pushed */
  int res_count = lua_tointeger(L, -1);

  /* Remove the number of values */
  lua_pop(L);

  return res_count;
}

C++相关问答推荐

如何通过Zephyr(Devicetree)在PR Pico上设置UTE 1?

C中空终止符后面的数字?

为什么在Linux(特别是Ubuntu 20.04LTS)上,POSIX共享内存对象在重启后仍然存在,然后突然变成了根用户?

创建一个fork导致fget无限地重新读取文件

ESP32在vTaskDelay上崩溃

#If指令中未定义宏?

在C++中头文件中声明外部 struct

从纯C中访问通用项对话框

用C宏替换strncMP函数中的参数

将宏值传递给ARM链接器,该链接器将变量放置在特定位置

调用mProtection将堆栈上的内存设置为只读,直接导致程序SIGSEGV

获取每个循环迭代结束时的当前时间

平均程序编译,但结果不好

getline()从c中的外部函数传递指针时输出null

用C++从外部ELF符号读取值

如何读取文件并将内容保存在字符串中?(在C语言中,没有崩溃或核心转储错误)

为什么argc和argv即使在主函数之外也能工作?

为什么孤儿进程在 Linux 中没有被 PID 1 采用,就像我读过的一本书中声称的那样?

为什么<到达*时不会转换为>?

我如何(合规地)从 tmpfile() 读取?