如何在c函数中保存状态

通常,我们在c函数中想要保存一些状态数据无非两种方式,全局变量或者静态变量,这些数据一般比程序本身生存期更久,但是在lua中这么做并不聪明,首选我们无法在c变量中保存一个lua对象,另外一旦使用了全局变量或者静态变量,那么该变量也就无法用于多个lua状态了。

熟悉的lua人都知道,对于非局部数据,lua的存放方式有全局变量、函数换将、非局部变量也叫closure(闭包),CAPI特提供了3种方式:注册表、环境和upvalue,注册表是个全局的table,它只能被c代码访问,一般用于保存在几个模块共享的数据,如果想保存一个模块的私有数据,可以使用环境,与lua函数一样,每个c函数都有自己的环境table,一个模块内的所有函数共享同一个环境table,因此它们之间可以共享数据,每一个c函数都可以拥有upvallue, 它是一种与特定函数相关联的lua值

注册表(registry)

注册表总是位于一个"伪索引"上,这个索引值由LUA_REGISTRYINDEX定义,它与lua栈索引类似,但不同的是它索引的值不在栈上,lua API中大多数函数都能接受伪索引,但是像lua_remove和lua_insert这种操作栈本身的函数只能使用普通栈索引,例如获取注册表中key为"Key"的值,可以这样写:

lua_getfield(L, LUA_REGISTRYINDEX, "Key");

注册表是一个普通的lua表,除了nil可以用任何值来索引它,因为所有的c模块共享同一个注册表,因此为了避免使用冲突,必须谨慎的选择key值,对于key名字的选择,没有绝对的避免冲突的方法,但是我们可以尽量做到不冲突,比如使用"通用唯一标识符(universal unique identifier ,uuid)"。

在注册表中不能使用数字类型的key,因为这种key是被"引用系统"保留的,这个系统是由辅助函数库中的一系列函数组成的,它可以在向一个table存储value时忽略如何
创建一个唯一的key,如:

//int luaL_ref (lua_State *L, int t);
//针对栈顶的对象,创建并返回一个在索引 t 指向的表中的 引用 (最后会弹出栈顶对象)。
//此引用是一个唯一的整数键。 只要你不向表 t 手工添加整数键, luaL_ref 可以保证它返回的键的唯一性。 你可以通过调用 lua_rawgeti(L, t, r) 来找回由 r 引用的对象。 
//函数 luaL_unref 用来释放一个引用关联的对象
//如果栈顶的对象是 nil, luaL_ref 将返回常量 LUA_REFNIL。 常量 LUA_NOREF 可以保证和 luaL_ref 能返回的其它引用值不同。 
int r = luaL_ref(L, LUA_REGISTRYINDEX);

luaL_ref函数会从栈中弹出一个值,然后用新分配的整数key来将这个值保存到注册表中,最后返回这个整数key,即引用

待续

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值