Lua中的元表用于函数调用拦截。

我正在尝试使用 Lua 元表来创建一个更美观的接口,用于访问一些内部的 C++ 函数。

这是到目前为止已经能正常工作的代码。(my.getmy.set 是在 C++ 中实现的)

function setDefault(t)
  local mt = {
  __index = function(tab,k) return my.get(t,k) end,
  __newindex = function(tab,k,v) return my.set(t,k,v) end,
  }
  _G[t] = {}
  setmetatable(_G[t],mt)
end

setDefault("LABEL")

LABEL.Text = "wibble" -- 等同于 my.set("LABEL","Text","wibble")
foo = LABEL.Text -- foo = my.get("LABEL","Text")

到目前为止还很好。下一步我想让它支持对表进行函数调用,比如下面的代码:

LABEL.Flash(500) -- 必须等同于 my.execute("LABEL","Flash", 500)

我知道这会调用 my.get("LABEL","Flash") —— 我可以让它返回一个 C++ 函数(使用 lua_pushcfunction),但是当调用 C++ 函数时,它缺少 LABELFlash 参数。

这是 my.get 的 C++ 片段。

static int myGet(lua_State * l)
{
  std::string p1(luaGetString(l, 1)); // table
  std::string p2(luaGetString(l, 2)); // 'method'

  if (isMethod(p1,p2))
  {
    lua_pushcfunction(l, myExec);
    lua_pushvalue(l, 1); // 再次将表推入栈中
    lua_pushvalue(l, 2); // 再次将方法推入栈中
    return 3;
  }
  else
  {
  // 在这里执行 my.get 逻辑。
  }
}
点赞
用户1737
用户1737

将其中的一个小改动,我得到了可行的结果:推送一个 C 闭包而不是 C 函数

  if (isMethod(p1,p2))
  {
    lua_pushvalue(l, 1); // 重新推送表
    lua_pushvalue(l, 2); // 重新推送方法
    lua_pushcclosure(l, myExecClosure,2);
    return 1;
  }

myExecClosure 就像 myExec,但是它通过上值(例如 luaupvaluindex(1))读取前两个参数,而不是从堆栈索引 1 和 2 读取。

2015-08-12 15:59:52