在Lua中添加到表中时,为什么要推送重复的键?

我正在从《Programming Gems 6》(第4.2章)学习如何使用类型检查将C++对象绑定到Lua。为了进行类型检查,将userdata/string组合存储在环境表中,并提供了如何执行此操作的代码:

void Binder::pushusertype(void* udata, const char* tname) {
 lua_pushlightuserdata(L, udata); // push address
 lua_pushvalue(L, -1);    // duplicate address
 lua_pushstring(L, tname);  // push type name
 lua_rawset(L, LUA_ENVIRONMENTINDEX); // envtable[address] = tname
}

其中Binder类具有Lua状态作为属性,名为“L”。

正如你所看到的,地址被推送了两次。由于这个小代码片段仅作为示例,似乎在堆栈上推送重复的地址在这个函数之外没有任何作用,这让我相信有一个特定的原因。所以我的问题是,为什么会这样做?

原文链接 https://stackoverflow.com/questions/3314986

点赞
stackoverflow用户399793
stackoverflow用户399793

你不需要处理。

lua_rawset会从栈中弹出tname和其副本,但会将原始的userdata留在栈上。 我不确定这是否是打印错误(似乎不太可能),我猜它以后可能会用到。 我不确定书中是否有更多提到这一点的内容,但这就是代码的作用。

2010-07-23 02:42:07
stackoverflow用户137317
stackoverflow用户137317

这个函数做了两件事:

  1. 将一个 lightuserdata 对象推入堆栈,当函数返回时,它将位于 lua 堆栈位置 -1 处。
  2. 它还通过存储在表键 address 中的名称 tname(等于 udata)更新当前函数环境。如果当前函数环境是普通全局环境,则等价的 Lua 代码为:
local x = <udata as lightuserdata>
_G[x] = <tname>

使用 x 的一个副本来执行 _G[x] = ...,另一个在函数返回时保留在堆栈上(与从 push 开始的函数名一致)。

2010-07-23 20:15:10