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?
source to share
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);
source to share
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;
}
source to share