zoukankan      html  css  js  c++  java
  • 编写C函数的技术-《lua程序设计》 27章 学习

    1.数组操作

    void lua_rawgeti(lua_State * L ,int index,int key)

    void lua_rewseti(lua_State * L,int index,int key)

    index表示table在栈的位置,key表示元素在table中的位置

    test.lua内容

    tab = {"a","b","c","c","e","f","g","h","i"}
    
    function ShowTable(tabb)
        print("显示table")
        for k,v in pairs(tabb) do
            print(v .. ' ')
        end    
    end
    
    ShowTable(tab)
    
    print(GetTableFromIndex(tab,6))
    SetTableFromIndex(tab,2,"aaaaaaaaaa")
    ShowTable(tab)
    static int GetTableFromIndex(lua_State * L )
    {
        //GetTableFromIndex(tab,6)
        int index = luaL_checkint(L,2);
        lua_rawgeti(L,1,index);
        const char *  ret = luaL_checkstring(L,-1);
        return 1;
    }
    static int SetTableFromIndex(lua_State * L )
    {
        //SetTableFromIndex(tab,2,"aaaaaaaaaa")
        int index = luaL_checkint(L,2);
        const char *  szNewValue = luaL_checkstring(L,3);
        lua_pushstring(L,szNewValue);
        lua_rawseti(L,1,index);
        return 0;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        lua_State * L = luaL_newstate();
        luaL_openlibs(L);
        lua_register(L,"GetTableFromIndex",GetTableFromIndex);
        lua_register(L,"SetTableFromIndex",SetTableFromIndex);
        if(0 != luaL_dofile(L,"test.lua"))
        {
            cout<<"error:"<<luaL_checkstring(L,-1)<<endl;
            lua_pop(L,1);
        }
        statckDump(L,"最后");
        lua_close(L);
        system("pause");
        return 0;
    }

    2.字符串操作

    lua_pushlstring(L,s+I,j-i+1) 把一个字符串区间为[I,j]传递给lua

    下面函数将一个字符串以分隔符生成一个表 例如调用 split(“he,3,66,22”) 会返回table {“he”,”3”,”66”,”22”}

    test.lua

    tableStrings = l_split("1111,2222,3333,4444,6666",",");
    ShowTable(tableStrings)
    static int l_split(lua_State * L )
    {
        const char * s = luaL_checkstring(L,1);  //第一个参数要分隔的字符串
        const char * sep = luaL_checkstring(L,2);   //第二个参数分隔符
        const char * e;
        int i = 1;
    
        lua_newtable(L); //创建返回值 
    
        //遍历所有字符串分隔
        while((e = strstr(s,sep)) != NULL)
        {
            lua_pushlstring(L,s,e-s);  //压入子串
            lua_rawseti(L,-2,i++);     //修改table
            s = e + 1;  //跳过分隔符
        }
        //压入最后一个子串
        lua_pushstring(L,s);
        lua_rawseti(L,-2,i);
        return 1;
    }

    还有一些相关的函数 lua_pushfstring,luaL_buffinit,luaL_addchar,luaL_add 等lua帮助文件都有说明

    3.在c函数中保存状态

    对于一个lua函数 来说,有3种地方可以保存非局部数据他们是,全局变量,函数环境和非局部的变量(closure中)

    3.1注册表

    注册表是位于一个”伪索引“上,这个索引值由LUA_REGISTRYINDEX定义。伪索引就像一个栈中的索引,但它所关联的值不在栈中。为了获取注册表中的key为”Key”的值,可以这么做

    lua_getfield(L,LUA_REGISTRYINDEX,”KEY”)

    在注册表中为了避免冲突的key尽量不要用常用的名字,在注册表中不应使用数字类型的key,因为这种key是被”引用系统“所保留的,这个系统由辅助库中的一系列函数组成,它可以在向一个table存储value时忽略如何创建一个唯一 的key

    int r = luaL_ref(L,LUA_REGISTRYINDEX);  //弹出一个值,然后用新分配的整数key来将这个值保存到注册表中,最后返回这个key,这个key被称为”引用 “

    lua_rewgeti(L,LUA_REGISTRYINDEX,r); //将与引用关联的值压入栈中

    luaL_unref(L,LUA_REGISTRYINDEX,r); //释放该值和引用

    3.2 C函数环境

    lua5.1开始每一个c函数都有自己的一个环境table一个函数可以像访问注册表一样通过一个伪索引来访问他的环境table环境table的伪索引是LUA_ENVIRONINDEX。在在C语言中设置环境的代码如下:

    int luaopen_foo(lua_State * L)
    {
        lua_newtable(L);
        lua_replace(L,LUA_ENVIRONINDEX);
        luaL_register(L,<库名>,<函数列表>);
        ...
    
    }

    3.3 upvalue

    注册表提供了全局变量的存储,环境提供了模块变量的存储,而upvalue机制则实现了一种类似于c语言中静态变量的机制。这种变量只在一个特定函数中可见。每当lua中创建一个函数时,都可以瘵任务数量的upvalue与这个函数关联

    将这种c函数与upvalue关联称为closureg一个c closure类似于Lua closure。closure可以用同一个函数代码来创建多个closure,每个closre可以拥有不同的upvalue

     

    static int counter(lua_State * L)
    {
        int val = lua_tointeger(L,lua_upvalueindex(1));  //luaj_upvalueindex可以生成一个upvalue的伪索引,注意这个索引可以像其它栈索引一样,但不存在于栈中
        lua_pushinteger(L,++val);  
        lua_pushvalue(L,-1);
        lua_replace(L,lua_upvalueindex(1)); //更新updavalue
        return 1;
    }
    int newCounter_(lua_State * L)
    {
        lua_pushinteger(L,0);  //创建cclosure前必须将cclosure初始值压栈
        lua_pushcclosure(L, //创建一个cclosure
            &counter, //基础函数
            1);  //upvalue个数
        return 1;
    }
  • 相关阅读:
    Redis宣言
    软件工程
    分布式编程
    编程泛型
    tcp/ip高效编程总结
    IP协议详解
    gevent程序员指南
    网站架构
    这些话,是乔布斯给世间留下的真正伟大礼物
    Flink/Spark 如何实现动态更新作业配置
  • 原文地址:https://www.cnblogs.com/zhangdongsheng/p/3427743.html
Copyright © 2011-2022 走看看