Nested lua_CFunction calls

What's the best way to work with nested lua_CFunction calls? Let's say I have two functions:

static int function2(lua_State *L) {
   int i = luaL_checkint(L, 1);

   /* do something */

   return 1;
};

static int function1(lua_State *L) {
   struct udata *u = luaL_checkudata(L, 1, UDATA_METATABLE);
   int i = luaL_checkint(L, 2);

   /* do something */

   /* this does not work, first on call stack is udata, not int */
   return function2(L);
};

      

The function call as above does not work. One option is to change function2()

to use the last item (index -1) on the stack, but this is not a solution at all, since it function2()

can be called from different places with different call stacks. Another way would be to replace return function2(L);

with

lua_pushcfunction(L, function2);
lua_pushvalue(L, 2);
lua_call(L, 1, 1);  /* need to know number of results */

      

I assume this gives function2()

its own call stack so there is no need to modify it. But this complication seems too complicated for functions with a large number of parameters, since it requires duplicating them all on the stack.

tl; dr: What's the recommended way / good way to call lua_CFunction

from another?

+3


source to share


3 answers


In function1

you expect the bottom of the stack to be user data. When you call function2

directly, LuaState hasn't changed and hence the bottom is still user data.

You can successfully call function2

from function1

by specifying an integer at index 1.

You can do this by calling lua_insert(L, 1)

that will move the top (assuming index 2) to index 1.



You can also do this by putting all values ​​by clicking on an integer:

lua_pop(L, lua_gettop(L));
lua_pushnumber(L, i);
return function2(L);

      

+2


source


lua_CFunction is not entirely a Lua function. It's just a way to create a Lua / closure function.

static int function1(lua_State *L) {
    ....
    int top = lua_gettop(L);
    lua_pushcfunction(L, function2);
    lua_pushvalue(L, 2);
    lua_call(L, 1, LUA_MULTRET);
    return lua_gettop(L) - 1;
}

      

Lua equivalent

function function1(arg)
  return (function(arg) --[[body of f2]] end)(arg)
end

      



This way you create a new function every time and call it. For a C function, this is perfectly fine, because you don't need to compile and you don't need an upvalue. In addition, Lua 5.2 introduces a lighting function for this. But if you want an equivalent for

int i = 1
local function function2(arg)
  i = i + 1
  ...
end

function function1(arg)
  return function2(arg)
end

      

You need a way to find a real Lua function eg. (not verified)

int f2_ref;

static int function1(lua_State *L) {

  ...

  -- push `function2` on stack
  lua_rawgeti(L, LUA_REGISTRYINDEX, f2_ref);

  -- as above
}

static int function2(lua_State *L) {
  int my_upvalue = lua_tonumber(L, lua_upvalueindex(1));
  my_upvalue++;
  lua_pushnumber(L, my_upvalue);
  lua_replace(L, lua_upvalueindex(1));


  ...
}

int luaopen_foo(lua_State *L){
  -- Here we create instance of Lua function(closure)
  lua_pushnumber(L, 1);
  lua_pushcclosure(L, function2, 1);
  f2_ref = luaL_ref(L, LUA_REGISTRYINDEX);

  lua_pushcclosure(L, function1, 0);
  return 1;
}

      

+1


source


I would say that calling it through lua is the recommended way to do it, but if you don't want to do it for some reason, then Timma's suggestions are correct.

0


source







All Articles