27.3.1 The Registry |
registry 一直位于一个由LUA_REGISTRYINDEX定义的值所对应的假索引(pseudo-index)的位置。一个假索引除了他对应的值不在栈中之外,其他都类似于栈中的索引。Lua API中大部分接受索引作为参数的函数,也都可以接受假索引作为参数—除了那些操作栈本身的函数,比如lua_remove,lua_insert。例如,为了获取以键值 "Key" 保存在registry中的值,使用下面的代码:
lua_pushstring(L, "Key");
lua_gettable(L, LUA_REGISTRYINDEX);
registry就是普通的Lua表,因此,你可以使用任何非nil的Lua值来访问她的元素。然而,由于所有的C库共享相同的registry ,你必须注意使用什么样的值作为key,否则会导致命名冲突。一个防止命名冲突的方法是使用static变量的地址作为key:C链接器保证在所有的库中这个key是唯一的。函数lua_pushlightuserdata将一个代表C指针的值放到栈内,下面的代码展示了使用上面这个方法,如何从registry中获取变量和向registry 存储变量:
/* variable with an unique address */
static const char Key = 'k';
/* store a number */
lua_pushlightuserdata(L, (void *)&Key); /* push address */
lua_pushnumber(L, myNumber); /* push value */
/* registry[&Key] = myNumber */
lua_settable(L, LUA_REGISTRYINDEX);
/* retrieve a number */
lua_pushlightuserdata(L, (void *)&Key); /* push address */
lua_gettable(L, LUA_REGISTRYINDEX); /* retrieve value */
myNumber = lua_tonumber(L, -1); /* convert to number */
我们会在28.5节中更详细的讨论light userdata。
当然,你也可以使用字符串作为registry的key,只要你保证这些字符串唯一。当你打算允许其他的独立库房问你的数据的时候,字符串型的key是非常有用的,因为他们需要知道key的名字。对这种情况,没有什么方法可以绝对防止名称冲突,但有一些好的习惯可以采用,比如使用库的名称作为字符串的前缀等类似的方法。类似lua或者lualib的前缀不是一个好的选择。另一个可选的方法是使用universal unique identifier(uuid),很多系统都有专门的程序来产生这种标示符(比如linux下的uuidgen)。一个uuid是一个由本机IP地址、时间戳、和一个随机内容组合起来的128位的数字(以16进制的方式书写,用来形成一个字符串),因此它与其他的uuid不同是可以保证的。