繁体   English   中英

嵌套的lua_CFunction调用

[英]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.

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