[英]How to declare a lua_CFunction that takes a single function argument on the stack?
[英]Nested lua_CFunction calls
处理嵌套lua_CFunction调用的最佳方法是什么? 假设我有两个这样的函数:
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);
};
上面的函数调用不起作用。 一种选择是修改function2()
以使用堆栈上的最后一个元素(索引-1),但这通常不是一个解法,因为可能从具有不同调用堆栈的各个地方调用function2()
。 另一种方法是替换return function2(L);
通过
lua_pushcfunction(L, function2);
lua_pushvalue(L, 2);
lua_call(L, 1, 1); /* need to know number of results */
我假设这给了function2()
自己的调用堆栈,所以不需要修改它。 但是对于具有更多参数的函数来说,这种解决方案似乎过于复杂,因为它需要在堆栈上复制所有参数。
tl; dr:推荐的方式/从另一个内部调用lua_CFunction
的好方法是什么?
在function1
您希望堆栈的底部是用户数据。 直接调用function2
,LuaState没有更改,因此底部仍然是用户数据。
您可以通过确保整数在索引1处从function1
成功调用function2
。
你可以通过调用lua_insert(L, 1)
来做到这一点,它将顶部(假设索引2)移动到索引1。
你也可以通过弹出所有值来推动整数:
lua_pop(L, lua_gettop(L));
lua_pushnumber(L, i);
return function2(L);
lua_CFunction不是完全Lua函数。 它只是一种创建Lua函数/闭包的方法。
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相当于
function function1(arg)
return (function(arg) --[[body of f2]] end)(arg)
end
因此,您每次创建新功能并调用它。 对于C函数来说它非常好,因为它不需要编译而且你不需要upvalue。 Lua 5.2也为此引入了光功能。 但如果你想要相同的
int i = 1
local function function2(arg)
i = i + 1
...
end
function function1(arg)
return function2(arg)
end
你需要一种方法来找到真正的Lua函数,例如(未测试)
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;
}
我会说通过lua调用它是建议的方法,但如果你不想因为某些原因那样做,那么Timma的建议是正确的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.