zoukankan      html  css  js  c++  java
  • 在C 函数中保存状态:registry、reference和upvalues

    在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# 串口通信总结
    客户端下载文件和服务器端下载文件总结
    Android 上传图片到 Asp.Net 服务器的问题
    iOS内存泄漏自动检测工具PLeakSniffer
    让iOS开发变得更有效率-分类、工具类
    分分钟解决iOS开发中App启动广告的功能
    响应者链及相关机制总结
    stackoverflow上关于iOS的票数最多(最常见)的15个问题
    iOS 开发之 ReactiveCocoa(进阶)
    iOS 开发之 ReactiveCocoa(基础)
  • 原文地址:https://www.cnblogs.com/yxysuanfa/p/7074466.html
Copyright © 2011-2022 走看看