在C 函数中保存状态:registry、reference和upvalues
在C函数中保存状态:registry、reference和upvalues
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指向同一个表。这样这个表就变成了一个全部函数共享数据的地方。
最新文章
- OC KVC
- SQL Server 2008 R2——TRUNCATE TABLE 无法截断表 该表正由 FOREIGN KEY 约束引用
- 管理权限<;八>;
- PostgreSQL Replication之第十二章 与Postgres-XC一起工作(3)
- c function
- ArcGIS Desktop 10.0 直连 ArcSDE 10.2
- IOS仿Android九宫格解锁效果[转]
- Creating SharePoint 2010 Event Receivers in Visual Studio 2010
- Python 自动化脚本学习(一)
- Android中通过耳机按键控制音乐播放的实现
- JAVA IP地址转成长整型方法
- mac安装lavaral
- hdu_1011(Starship Troopers) 树形dp
- Flask Web中文教程
- odoo11登录之后返回的session信息分析
- isinstance和issubclass,__getattribute__,__getitem__,__setitem__,delitem__,__str__(三十五)
- SILC超像素分割算法详解(附Python代码)
- Windows下利用TortoiseSVN搭建本地SVN服务器
- java虚拟机的内存划分
- dwz(jui)刷新当前dialog的方法