简体   繁体   中英

How to access the return value of a C function called by lua_pcall?

I have this function:

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);
}

I would like to have generic_pcall_wrapper() to return the value returned by sum().

Note that this function should take many different functions, and how they deal with the return values is unspecified, the only reliable value is the number returned by each of those functions.

The first thing which I don't quite understand is the need for lua_pop in the sum function. This call to lua_pop is quite unusual and not present in 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;
}

Regarding the original question, in the callback sum , the return value represent how many results have been pushed on the stack. This value is consumed by the Lua runtime and is not available to the user of the Lua API. So if this value is needed later by the API user, it is needed to save this value using the Lua functions.

With the Lua API, a natural way to do that would be to push it on the stack.

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 */
}

Then:

  1. The generic wrapper get the number of returned values on the stack
  2. The wrapper remove this special value from the stack
  3. Return to the number of values to the caller
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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM