3

ネストされた lua_CFunction 呼び出しを処理する最良の方法は何ですか? 次のような 2 つの関数があるとします。

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 つのオプションは、スタックの最後の要素 (インデックス -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別の内部からa を呼び出す推奨される方法/良い方法は何ですか?

4

3 に答える 3

3

スタックの一番下がユーザーデータでfunction1あると予想しています。直接呼び出した場合function2、LuaState は変更されていないため、下部はまだユーザー データです。

整数がインデックス 1 であることを確認することで、function2fromを正常に呼び出すことができます。function1

lua_insert(L, 1)これを行うには、一番上 (インデックス 2 を想定) をインデックス 1 に移動する which を呼び出します。

整数を押し戻すすべての値をポップすることで、これを行うこともできます。

lua_pop(L, lua_gettop(L));
lua_pushnumber(L, i);
return function2(L);
于 2014-11-17T23:03:11.800 に答える
1

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 ではそのための light 関数が導入されています。しかし、同等のものが必要な場合

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;
}
于 2014-11-18T14:04:09.820 に答える