Lua C 保存状态

来源:互联网 发布:开淘宝店做淘宝客 编辑:程序博客网 时间:2024/04/28 08:19

转自lua程序设计第二版
C API提供3中地方存放非局部数据

注册表

一个全局的table,只能被C代码访问,通常可以用它来保存那种需要在几个模块中共享的数据注册表总是位于一个"伪索引"上,这个索引值由LUA_REGISTRYINDEX定义。Lua API中的大多数函数都能接受伪索引,但像lua_remove和lua_insert这种操作栈本身的函数却只能使用普通索引。```C++lua_getfield(L,LUA_REGISTRYINDEX,"key");``` 注册表是一个普通的lua table,可以用任何Lua值(除了nil)来索引。然而,由于所有的C模块共享同一个注册表,为了避免冲突,必须谨慎的选择key的值。注册表中不应使用数字类型的key,因为这种key是被"引用系统"所保留的。这个系统是由辅助库中的一系列函数组成的,它可以在向一个table存储value时,忽略如何创建一个唯一的key。```C++//从栈中弹出一个值,然后用一个新分配的整数key来将这个值保存到注册表中,最后返回这个整数。这个key被称为"引用"。int r = luaL_ref(L,LUA_REGISTRYINDEX);//将与引用关联的值压入栈中lua_rawgeti(L,LUA_REGISTRYINDEX,r);//释放该值与引用luaL_unref(L,LUA_REGISTRYINDEX,r);//为一个nil值调用luaL_ref时,并不会创建新引用,而是返回一个常量引用LUA_REFNILluaL_unref(L,LUA_REGISTRYINDEX,LUA_REFNIL);//会压入一个nillua_rawgeti(L,LUA_REGISTRYINDEX,LUA_REFNIL);```

通过lua_pushlightuserdata保存字符串

static char key = 'k';//保存一个字符串//压入地址lua_pushlightuserdata(L,(void*)&key);//压入值lua_pushstring(L,mystr);//registry[&key] = mystrlua_settable(L,LUA_REGISTRYINDEX);//检索一个字符串//压入地址lua_pushlightuserdata(L,(void*)&key);//检索值lua_gettable(L,LUA_REGISTRYINDEX);//转换成字符串myStr = lua_tostring(L,-1);

环境

保存一个模块私有数据,每个C函数都有自己的环境table(从Lua5.1开始)。通常,一个模块内的所有函数共享同一个环境table,由此它们可以共享数据。一个函数可以像访问注册表那样,通过一个伪索引来访问它的环境table。环境table的伪索引是LUA_ENVIRONINDEX```C++int luaopen_foo(lua_State *L){    //创建一个新的table用于共享环境    lua_newtable(L);    //将这个table设为当前环境    lua_replace(L,LUA_ENVIRONINDEX);    luaL_register(L,<库名>,<函数列表>);    ...}```尽可能用环境代替注册表,除非需要在不同模块间共享数据。

upvalue

与特定函数相关联的Lua值,这种变量只在一个特定的函数中可见。```C++static int counter(lua_State *L){    intvalue= lua_tointeger(L,lua_upvalueindex(1));    //新的值    lua_pushinteger(L,++val);    //复制它    lua_pushvalue(L,-1);    //更新upvalue    lua_replace(L,lua_upvalueindex(1));    return 1;}int newCounter(lua_State *L){    //在创建closure前,必须将upvalue的初值压入栈中。    lua_pushinteger(L,0);    //创建一个新的closure(第二个参数是一个基础函数,第三个参数是upvalue的数量)    //并将新的closure留在了栈上,并以此作为newCounter的返回值。    lua_pushclosure(L,&counter,1);    return 1;}```

通过upvalue实现元组

未完待续

0 0
原创粉丝点击