在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的更多相关文章

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

    C函数可以通过堆栈来和Lua交换数据,但有时候C函数需要在函数体的作用域之外保存某些Lua数据,那么我们想到全局变量或static变量,这样做的缺点是:(1)为Lua设计C函数库时,导致不可重入:(2 ...

  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. 高效管理 Elasticsearch 中基于时间的索引——本质是在利用滚动模式做数据的冷热分离,热索引可以用ssd

    高效管理 Elasticsearch 中基于时间的索引 转自:http://stormluke.me/es-managing-time-based-indices-efficiently/ 用 Ela ...

  2. Linux下清屏的方法

    转自“https://blog.csdn.net/lis_12/article/details/54943626” clear,刷新屏幕,本质上是让终端显示页向后翻了一页,如果向上滚动屏幕还可以看到之 ...

  3. 在量化金融中15个最流行的Python数据分析库

    Python是当今应用最广泛的编程语言之一,以其效率和代码可读性著称.作为一个科学数据的编程语言,Python介于R和java之间,前者主要集中在数据分析和可视化,而后者主要应用于大型应用.这种灵活性 ...

  4. Vim常用又容易忘的命令

    一篇讲的不错的教程 :noh 取消搜索高亮 x 删当前光标所在的一个字符. :wq 存盘 + 退出 dd 删除当前行,并把删除的行存到剪贴板里 p 粘贴剪贴板 a → 在光标后插入 /pattern ...

  5. 读<<大数据时代>>的一些感想

    第一次听说<<大数据时代>>这本书,是在网上看到的央视搞的一个2013中国好书评选活动推荐的25本“中国好书”的榜单中看到的.然后迅速上豆瓣上查看了一下对该书的评价,一看非常高 ...

  6. 重载(overload)和重写(override)的对比(笔试经常出)

    Day04_SHJavaTraing_4-6-2017 1.重载(overload):    ①权限修饰符(public private 默认):        无关    ②返回值类型:       ...

  7. 杭电 2095 find your present (2)【位运算 异或】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2095 解题思路:因为只有我们要求的那个数出现的次数为奇数,所以可以用位运算来做,两次异或同一个数最后结 ...

  8. 01--数据结构——动态链表(C++)

    数据结构——动态链表(C++)   定义一个节点: [cpp] view plain copy   print? #include <iostream> using namespace s ...

  9. 文件IO详解(四)---标准输入、标准输出和标准错误

    每个进程都会默认打开3个文件描述符,即0.1.2.其中0代表标准输入流.1代表标准输出流.2代表标准错误流.通常标准输入流对应着键盘的设备文件.标准输出流和错误流对应着显示器的设备文件.在编程中通常使 ...

  10. MVC 接收文件

    [HttpPost] public ActionResult Layedit() { var files = Request.Files; //获得所上传的所有文件 ) { HttpPostedFil ...