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. Android onTouch事件传递机制

    Android onTouch事件介绍: Android的触摸事件:onClick, onScroll, onFling等等,都是由许多个Touch组成的.其中Touch的第一个状态肯定是ACTION ...

  2. Leetcode-462 Minimum Moves to Equal Array Elements II

    #462.   Minimum Moves to Equal Array Elements II Given a non-empty integer array, find the minimum n ...

  3. activemq安全设置 设置admin的用户名和密码

    ActiveMQ使用的是jetty服务器, 打开conf/jetty.xml文件,找到 <bean id="securityConstraint" class="o ...

  4. 流媒体选择Nginx是福还是祸?

    CDN,视频云,已经“僧多粥少” 视频直播的持续升温,无意间也让带宽生意的争夺变得异常残酷.一时间,各种云计算.CDN.视频云提供商都在视频尤其是直播上投入重兵,揭竿而起的新生起义军们也正马不停蹄的赶 ...

  5. Why数学图像生成工具

    该软件能够以给定的数学公式及算法生成各种绚烂的数学图像.软件中有两种生成图像的方法: (1)通过一种我自定义的脚本语言生成: 软件中定义一套简单易学的脚本语言,用于描述数学表达式.使用时需要先要将数学 ...

  6. XsdGen:通过自定义Attribute与反射自动生成XSD

    前言 系统之间的数据交互往往需要事先定义一些契约,在WCF中我们需要先编写XSD文件,然后通过自动代码生成工具自动生成C#对象.对于刚刚接触契约的人来说,掌握XMLSpy之类的软件之后确实比手写XML ...

  7. TaskHosting - 开发桌面工具原来还可以这么简单

    由来 对于喜欢开发的我经常会写一些小工具,这些小工具多以功能为主,不要求漂亮.个性化的UI.但起码要保证使用方便,因此最基本的功能要有: GUI(图片用户界面) 程序配置的保存与读取(让用户在GUI上 ...

  8. javascript一种新的对象创建方式-Object.create()

    1.Object.create() 是什么? Object.create(proto [, propertiesObject ]) 是E5中提出的一种新的对象创建方式,第一个参数是要继承的原型,如果不 ...

  9. 定时从远程的数据库中取数据,然后把取出来的数据插入或更新本地的oracle数据库的表

    最近项目中有一种需求: 大致需求是这样的 通过给定的 用户名和密码 要定时从远程的数据库中取数据,然后把取出来的数据插入或更新本地的oracle数据库的表 项目的结构式struts1 hibernat ...

  10. wordpress自动保存远程图片插件 DX-auto-save-images

    wordpress自动保存远程图片插件DX-auto-save-images 解决了保存文章就可以自动将远程图片保存到你的服务器上了. 具体操作步骤如下: 1.安装启用wordpress自动保存远程图 ...