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, );
lua_pushcclosure(L, &counter, );
return ;
} // C函数
static int counter (lua_State *L)
{
double val = lua_tonumber(L, lua_upvalueindex());
lua_pushnumber(L, ++val); /* new value */
lua_pushvalue(L, -); /* duplicate it */
lua_replace(L, lua_upvalueindex()); /* update upvalue */
return ; /* 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的更多相关文章

  1. 在C 函数中保存状态:registry、reference和upvalues

    在C函数中保存状态:registry.reference和upvalues      C函数能够通过堆栈来和Lua交换数据,但有时候C函数须要在函数体的作用域之外保存某些Lua数据.那么我们想到全局变 ...

  2. LUA 在C函数中保存状态:registry、reference

    1 背景 lua的值一般都是保存在栈里面,调用函数完毕值在栈会被清掉,从而被GC回收.但有时候C函数需要在函数体的作用域之外保存某些Lua数据,这些数据不能存放在栈里面,有没有全局变量之类的可以存放. ...

  3. 程序中保存状态的方式之Cookies

    程序中保存状态的方式之 Cookies,之前写过一篇关于ViewState的.现在继续总结Cookies方式的 新建的测试页面login <%@ Page Language="C#&q ...

  4. 程序中保存状态的方式之ViewState

    程序中保存状态的方式有以下几种: 1.Application 2.Cookie 3.Session 4.ViewState:ViewState是保存状态的方式之一,ViewState实际就是一个Hid ...

  5. 在c中保存状态

    1. 注册表 注册表是一个普通的table,我们可以将c函数中需要保存的状态都存储在注册表中,注册表是可以被多个c模块共享的. 由于注册表是一个普通table,我们同样可以在栈中对其进行操作,只是这个 ...

  6. Spring MVC不要在@Service bean中保存状态

    先看这么一段代码: @Service public class AccountService { private String message; public void foo1() { if (tr ...

  7. Android菜鸟的成长笔记(15)—— Android中的状态保存探究(下)

    原文:Android菜鸟的成长笔记(15)-- Android中的状态保存探究(下) 在上一篇中我们简单了解关于Android中状态保存的过程和原理,这一篇中我们来看一下在系统配置改变的情况下保存数据 ...

  8. 【React】377- 实现 React 中的状态自动保存

    点击上方"前端自习课"关注,学习起来~ 作者:陈俊宇 https://github.com/CJY0208 什么是状态保存? 假设有下述场景: 移动端中,用户访问了一个列表页,上拉 ...

  9. 19.在HTTP 1.0中,状态码401的含义是(?);如果返回“找不到文件”的提示,则可用 header 函数,其语句为(?)写出http常见的状态码和含义,至少5个.[完善题目]

    状态401代表未被授权,header("Location:www.xxx.php"); 100-199 用于指定客户端应相应的某些动作. 200-299 用于表示请求成功. 300 ...

随机推荐

  1. 前端框架layui

    可以了解下jQuery组件layer layui开始使用Layui兼容除IE6/7以外的全部浏览器,并且绝大多数结构支持响应式 弹出层如果你使用的是Layui,那么你直接在官网下载layui框架即可, ...

  2. PHP类与面向对象

    PHP常量PHP常量大写PHP常量用define函数或const关键字定义一个常量一旦被定义,就不能再改变或者取消定义.在 PHP 5.3.0 以后,可以使用 const 关键字在类定义之外定义常量. ...

  3. hibernate(二)一级缓存和三种状态解析

    序言 前一篇文章知道了什么是hibernate,并且创建了第一个hibernate工程,今天就来先谈谈hibernate的一级缓存和它的三种状态,先要对着两个有一个深刻的了解,才能对后面我要讲解的一对 ...

  4. 几种web数据渲染模板对比

    在web开发,实现视图.数据的分离,由前端工程师专门负责编写html页面,有php后台工程师写php接口返回json数字,那么中间如何将json数据绑定到html页面上有几种方法呢.基于这种需求大体上 ...

  5. android: SQLite 数据库的最佳实践

    6.5.1    使用事务 前面我们已经知道,SQLite 数据库是支持事务的,事务的特性可以保证让某一系列的操 作要么全部完成,要么一个都不会完成.那么在什么情况下才需要使用事务呢?想象以下场 景, ...

  6. raspberry pi 如何汉化显示中文

    1 树莓派初装系统之后,首次启动会出现“raspi-config”工具,如下图:(若不是初次启动,在命令模式下,请输入 sudo raspi-config 命令,即可调出此界面.若在图形桌面下,打开桌 ...

  7. PHP之算法偶遇隨感

    php真的很棒,很多函數把我們想要的功能都簡單實現了,是項目快速開發的首選.說實話,在BS程序開發方面我認為最好的兩種語言是PHP和JSP,我之前曾學過一段時間的java,確實很棒完全的OOP,但是它 ...

  8. BigDecimal除法运算出现java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result的解决办法

    BigDecimal除法运算出现java.lang.ArithmeticException: Non-terminating decimal expansion; no exact represent ...

  9. ORA-00257: archiver error. Connect internal only, until freed——解决

    参考http://www.2cto.com/database/201109/104615.html, 开启归档后,操作一个大表迁移表空间,执行了1个多小时没完成就手动给中断了,但是再次用plsql登陆 ...

  10. Codeforces Round #382 (Div. 2)B. Urbanization 贪心

    B. Urbanization 题目链接 http://codeforces.com/contest/735/problem/B 题面 Local authorities have heard a l ...