lua 在C函数中保存状态:registry、reference和upvalues
2016-11-14 11:36
316 查看
在C函数中保存状态:registry、reference和upvalues
C函数可以通过堆栈来和Lua交换数据,但有时候C函数需要在函数体的作用域之外保存某些Lua数据,那么我们想到全局变量或static变量,这样做的缺点是:(1)为Lua设计C函数库时,导致不可重入;(2)不是所有的Lua值都能很好的保存到C变量中。那么可不可以将值保存在Lua全局变量里面呢,可以,Lua就提供了一个独立的被称为registry的表,但是Lua代码本身不能访问它。1、registry全局注册表
解释:一个普通的Lua表,使用假索引(pseudo-index)LUA_REGISTRYINDEX访问。C代码可以访问,Lua代码不能访问。
用途:解决C函数保留全局Lua值的问题。
注意:所有的C库共享相同的registry,所以对于key的命名需要具有全局唯一性。
// 获取registry表键值"KEY"对应的值的方法: lua_pushstring(L, "KEY"); lua_gettable(L, LUA_REGISTRYINDEX);
2、reference引用系统
解释:通过一个整数来唯一标识一个Lua数据对象,由两个函数luaL_ref和luaL_unref组成,这对函数用来不需要担心名称冲突的将值保存到registry中去。
用途:将一个指向Lua值的reference存储到一个C结构体中,这个reference是一个int的KEY。
注意:栈顶值为nil的时候,不会产生reference,luaL_ref函数会返回LUA_REFNIL,而对LUA_REFNIL解引用是没有效果的。
重要函数:
int luaL_ref (lua_State *L, int t);
创建并返回一个引用reference,并将[reference,栈顶值v]加入t对应的表中。
void luaL_unref (lua_State *L, int t, int ref);
解引用,将t对应的表中的[reference,v]键值对删除。
// 对栈顶的值v生成一个引用,即将[r, v]存到LUA_REGISTRYINDEX表中 int r = luaL_ref(L, LUA_REGISTRYINDEX); // 将一个引用值入栈 lua_rawgeti(L, LUA_REGISTRYINDEX, r); // 解引用,即释放reference和值 luaL_unref(L, LUA_REGISTRYINDEX, r);
3、upvalues机制
解释:当创建一个C函数时可以关联一些值,这样就创建了一个C闭包,这些关联值就叫做upvalues。
用途:实现了与C static变量等价的概念,这种变量只能在特定的函数内可见。
使用:通过lua_upvalueindex(n)生成假索引来访问。
// 预声明 static int counter (lua_State *L); // 创建C闭包的工厂函数 int newCounter (lua_State *L) { lua_pushnumber(L, 0); lua_pushcclosure(L, &counter, 1); return 1; } // C函数 static int counter (lua_State *L) { double val = lua_tonumber(L, lua_upvalueindex(1)); lua_pushnumber(L, ++val); /* new value */ lua_pushvalue(L, -1); /* duplicate it */ lua_replace(L, lua_upvalueindex(1)); /* update upvalue */ return 1; /* return new value */ }
注意:永远不要使用数字作为registry 的key,因为这种类型的key是保留给reference系统使用。
假索引(pseudo-index)的特点:(1)对应的值不在栈中;(2)使用方式类似于栈索引,大多数接受索引为参数的函数都能使用;(3)那些操作栈本身的函数不能使用假索引,比如lua_remove,lua_insert等。
与Lua闭包(在Lua代码中,一个闭包是一个从外部函数访问局部变量的函数)不同的是,C闭包不能共享upvalues:每一个闭包都有自己独立的变量集。然而,我们可以设置不同函数的upvalues指向同一个表,这样这个表就变成了一个所有函数共享数据的地方。
相关文章推荐
- 在C函数中保存状态:registry、reference和upvalues
- LUA 在C函数中保存状态:registry、reference
- 在C 函数中保存状态:registry、reference和upvalues
- 在C函数中保存状态:registry、reference和upvalues
- 在C 函数中保存状态:registry、reference和upvalues
- 在C函数中保存状态:registry、reference和upvalues
- [Lua]在C函数中保存状态--注册表,环境表,upvalue
- [Lua]在C函数中保存状态--注册表,环境表,upvalue
- lua如何在游戏中保存上一次游戏状态
- lua如何在游戏中保存上一次游戏状态
- Android 屏幕旋转时保存状态
- Android中保存Activity的状态
- 使用cookie保存用户的登录状态——初步实现
- 全选翻页后保存状态
- Lua中调用C函数(lua-5.2.3)
- html5 canvas学习--canvas保存于恢复状态
- cookie保存登陆状态实现
- 使用SQL Server保存Session状态,实现单点登录
- 如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?
- Android 应用保存状态