3

因此,使用 Lua C API,您可以将 Lua 值保存在注册表中并稍后检索它。有不同的方法可以做到这一点,您可以创建一个变量并将其指针用作注册表中的键,因为它始终是唯一的。您将指针作为轻用户数据推送。

您还可以使用LuaL_ref(L, LUA_REGISTRYINDEX). 一个比另一个有什么优势?什么时候使用引用,什么时候使用指针?

还有引用,因为它被称为引用,如果 Lua 垃圾收集器收集 Lua 值,注册表中的值会是nil? 如果 Lua 更新了 Lua 值,注册表中的值是否也会改变?

4

2 回答 2

2

Lua 注册表只是另一个 lua 表,可以通过预定义的“特殊”索引轻松访问。我想您不需要解释 Lua 表与轻用户数据有何不同。
您将如何索引注册表并不重要,只要您可以将该键存储在 C/C++ 端即可。为了您的方便,已经有函数(luaL_ref/luaL_unref)为您提供易于存储和移动的整数键。

关于垃圾收集 - 规则始终相同。只要值存储在未标记为弱表的表中(注册表不是弱表),该值就不会被清除。您必须从注册表中显式删除值。

更改值将遵循正常的 Lua 规则。将新的不可变值分配给某个变量不会更改存储在注册表中的值,即注册表不会跟随某个变量的更新。但是更改可变值(表等)的内容是可以的,因为注册表和变量将引用相同的值。

于 2016-10-22T11:02:13.670 回答
2

除了之前的答案:

lightuserdataLua和Lua 的区别userdata

lightuserdata是包含 C 指针的特殊 Lua 类型(以及nil, boolean, number, string, table,等)。thread而已。您不能将 metatable 分配给lightuserdata. 相反,您可以将元表分配给userdata类型。例如参见Lua 文件操作,其中文件句柄userdata与方法一起使用。f:read("*all")f 是userdata命令相当于f.read(f, "*all")

LUA_REGISTRYINDEX使用整数或 C 指针进行索引

有两种方法在注册表中被广泛使用。

  1. 创建对 Lua 值的新引用,luaL_ref并将返回的整数值存储在代码中的某处。即,要访问 Lua 值,您需要读取包含引用和索引注册表的 C 变量,lua_rawgeti(L, LUA_REGISTRYINDEX, i)其中该整数值在哪里。lua_rawseti(L, LUA_REGISTRYINDEX, i)也可以,但不要尝试用这种方法重写为 nil 值!

  2. 您创建一个静态 C 变量static int myvar;,然后直接使用lua_rawgetp(L, LUA_REGISTRYINDEX, &myvar)lua_rawsetp(L, LUA_REGISTRYINDEX, &myvar)操作存储的 Lua 值。

不幸的是,我无法比较两种方法的性能。我认为它们几乎相同。

于 2016-10-23T00:43:01.373 回答