• lua


        Lua 是一个小巧的脚本语言。是巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个研究小组,由Roberto Ierusalimschy、Waldemar Celes 和 Luiz Henrique de Figueiredo所组成并于1993年开发。 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。Lua由标准C编写而成,几乎在所有操作系统和平台上都可以编译,运行。Lua并没有提供强大的库,这是由它的定位决定的。所以Lua不适合作为开发独立应用程序的语言。Lua 有一个同时进行的JIT项目,提供在特定平台上的即时编译功能。
        Lua脚本可以很容易的被C/C++ 代码调用,也可以反过来调用C/C++的函数,这使得Lua在应用程序中可以被广泛应用。不仅仅作为扩展脚本,也可以作为普通的配置文件,代替XML,ini等文件格式,并且更容易理解和维护。[1] Lua由标准C编写而成,代码简洁优美,几乎在所有操作系统和平台上都可以编译,运行。 一个完整的Lua解释器不过200k,在目前所有脚本引擎中,Lua的速度是最快的。这一切都决定了Lua是作为嵌入式脚本的最佳选择。

    保存和运行

        运行可以通过 Lua 的交互模式,也可以用记事本编辑代码保存为 .lua 的格式,通过 lua 编译器运行。也可以通过第三方工具,将 lua 打包独立运行。

    目标

        Lua的目标是成为一个很容易嵌入其它语言中使用的语言。大多数程序员也认为它的确做到了这一点。
    很多应用程序、游戏使用LUA作为自己的嵌入式脚本语言,以此来实现可配置性、可扩展性。这其中包括魔兽世界、博德之门、愤怒的小鸟、VOCALOID3、太阳神三国杀 等。

    特性

    轻量级
        轻量级Lua语言的官方版本只包括一个精简的核心和最基本的库。这使得Lua体积小、启动速度快,从而适合嵌入在别的程序里。5.0.2版的Lua的内核小于120KB,而Python的内核大约860KB,Perl的内核大约1.1MB。[2]
    可扩展
        可扩展 Lua并不象其它许多"大而全"的语言那样,包括很多功能,比如网络通讯、图形界面等。但是Lua提供了非常易于使用的扩展接口和机制:由宿主语言(通常是C或C++)提供这些功能,Lua可以使用它们,就像是本来就内置的功能一样。
    其它特性
        Lua还具有其它一些特性:同时支持面向过程(procedure-oriented)编程和函数式编程(functional programming);自动内存管理;只提供了一种通用类型的表(table),用它可以实现数组,哈希表,集合,对象;语言内置模式匹配;闭包(closure);函数也可以看做一个值;提供多线程(协同进程 [3] ,并非操作系统所支持的线程)支持;通过闭包和table可以很方便地支持面向对象编程所需要的一些关键机制,比如数据抽象,虚函数,继承和重载等。

    示例代码

        

        是的,你猜对了:hello world
    1
    print"Hello,world!"
        一个比较复杂一点的例子,但是它展示了什么是闭包:
    1
    2
    3
    4
    5
    6
    7
    function create_a_counter()
        local count=0
        return function()
        count = count + 1
        return count
        end
    end
        create_a_counter()返回一个记数器,每次调用这个记数器,都会得到一个比上次大1的值。
        注意:调用的时候,如果你的调用是这样的的:
        print(create_a_counter())
        那么每次输出是一样的结果,没有计数的效果。
        应该这样调用:
        c1=create_a_counter()
        print(c1()) --> 1
        print(c1()) --> 2

    数据交换

    介绍
        Lua和C程序通过一个栈交换数据: struct lua_State
        栈的序号可以从栈顶和栈底计数,从栈底计数,则栈底是1,向栈顶方向递增。从栈顶计数,则栈顶是-1,向栈底方向递 减。一般都用从栈顶计数的方式。栈的默认大小是20,可以用lua_checkstack修改.用lua_gettop则可以获得栈里的元素数目。并不是 说在栈顶有一个整形元素。而是计算了一下栈顶元素在栈里的正index,相当于元素数目。
        Lua 调用C函数用的栈是临时的,调用结束之后就被销毁了。
        如何从栈中获取从Lua脚本中的参数
        如果知道Lua脚本中某个全局变量的名字,可以用
    1
    void lua_getglobal(lua_State *L, const char *name)
        这个函数会将name所指Lua变量的值放在栈顶.
        如果是在C 函数中要获取Lua调用函数使用的参数:
        首先用lua_gettop检查参数数量
        用lua_is 类函数检测参数的类型,做好错误处理
        用lua_to 类函数将参数转换为number或者string。(对Lua来说,只有这两种简单类型)
    1
    2
    lua_tonumber返回的是double
    lua_tostring返回的是char*
        用lua_remove从栈中删除掉元素
        继续获取下一个元素。 因为每次都调用lua_remove,所以每次调用lua_tonumber,使用的index都将固定是-1,即栈顶。
        如果lua_istable成立,那么说明栈顶是一个table 注意 tabl e是不能取出来的,只能把 table 里的元素一个个取出来。
        首先把元素的名字压入栈顶:
    1
    lua_pushstring(L, "i");
        然后就可以用lua_gettable调用,值会放在栈顶。同时刚才压入的元素名字被弹出。用上面的办法,可以把这个值取出来。记得也应该 lua_remove。 如果table的某一个元素也是table,重复即可。当table的所有元素都取完了,记住这个table本身还在栈里,要用lua_remove把它 删除。
        如果要获取的是一个数组(所谓数组,其实就是key是从1开始的数字序列的table,并且值类型相同),用lua_next可以遍历这个数组:
        首先lua_pushnil,压入一个空值,然后
    1
    2
    3
    4
    5
    6
    7
    8
    9
    while(lua_next(L, -2)!=0)
    {
        if(lua_isnumber(L, -1))//判断元素类型,也可能是string
        {
            arrf.add((float)lua_tonumber(L, -1));//获取元素的值
            lua_remove(L, -1);
        }
    }
    lua_remove(L,-1);//删除NIL
        如何从C返回数据给Lua脚本
        用 lua_push 类函数压入数据到栈中,并用return n;来告诉Lua返回了几个返回值。 Lua是天生支持多个返回值的,如
    1
    x,y = Test()
        Lua会根据n从栈里取相应的数据。
        如果要返回一个table:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    lua_newtable(L);            //创建一个表格,放在栈顶
    lua_pushstring(L,"mydata"); //压入key
    lua_pushnumber(L,66);        //压入value
    lua_settable(L,-3);         //弹出key,value,并设置到table里面去
    lua_pushstring(L,"subdata");//压入key
    lua_newtable(L);            //压入value,也是一个table
    lua_pushstring(L,"mydata"); //压入subtable的key
    lua_pushnumber(L,53);
    valuelua_settable(L,-3);    //弹出key,value,并设置到subtable
    lua_settable(L,-3);         //这时候父table的位置还是-3,弹出key,value(subtable),
                                //并设置到table里去
    lua_pushstring(L,"mydata2");//同上
    lua_pushnumber(L,77);
    lua_settable(L,-3);
    return1;
     
    //栈里现在就一个table其他都被弹掉了。如果要返回一个数组,
    //用如下代码:(注意那个关于trick的注释,我在等官方的解释。
    //经过验证,这个问题只在windows版本调用dll中方法的时候出现。WinCE正常)
    lua_pushstring(L,"arri");
    lua_newtable(L);
    {
        //atrick:otherwisetheluaenginewillcrash.ThiselementisinvisibleinLuascript
        lua_pushnumber(L,-1);
        lua_rawseti(L,-2,0);
        for(int i=0; i<arri.size(); i++)
        {
            lua_pushnumber(L, arri);
            lua_rawseti(L, -2, i+1);
        }
    }
    lua_settable(L,-3);
    这样产生的数组可以在Lua中如下遍历:
    1
    2
    3
    4
    for i,v ini pairs(data.arri)
    do
        print(v)
    end
    或者是
    1
    2
    3
    4
    for i=1,table.getn(data.arri)
    do
     print(data.arri)
    end
        只有数组才能这样,name,value构成的Record不行,table.getn也只对数组有效。
        由于上述代码的高度相似性,所以很容易实现自动生成这些代码。比如,根据C的一个struct定义:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    typedef enum{BR_9600,BR_4800,}BaudRate;
    typedef struct flag
    {
        int    onoff;
        int    j;
        long    l;
        double    d;
        char    *name;
        BaudRate    rate;
    }flag;

      可以自动产生如下代码:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    bool DataToLua(flagdata, lua_State*L)
    {
        lua_newtable(L);
        lua_pushstring(L, "onoff");
        lua_pushnumber(L, double)data.onoff);
        lua_settable(L, -3);
        lua_pushstring(L, "j");
        lua_pushnumber(L, (double)data.j);
        lua_settable(L, -3);
        lua_pushstring(L, "l");
        lua_pushnumber(L, (double)data.l);
        lua_settable(L, -3);
        lua_pushstring(L, "d");
        lua_pushnumber(L, double)data.d);
        lua_settable(L, -3);
        lua_pushstring(L, "name");
        lua_pushstring(L, data.name.c_str());
        lua_settable(L, -3);
        lua_pushstring(L, "rate");
        lua_pushnumber(L, (double)(int)data.rate);
        lua_settable(L, -3);
        return true;
    }
        LuaToData也是类似的。
        如果使用面向对象的方式封装起flag来,把DataToLua变成flag类的一个方法,就更加方便了。

    在线手册

    Lua中文版在线手册。
     

    使用项目

    Minecraft中的电脑模组(ComputerCraft)
        所有的为电脑和turtle(机器人)的代码都是基于Lua的,你可以用它们与有(无)线路由器、打印机、磁盘驱动器、(黄金)显示器互动。
    Adobe Photoshop Lightroom
        Lightroom是Adobe公司的一款摄影后期制作软件,最开始的版本由Shadowland代码编写,后期版本部分使用Lua实现,Lua代码占到代码总量的63%。
    金庸群侠传lua复刻版
        这个游戏,游戏迷们想必都玩过了。牛人用lua脚本重新弄了下。
    魔兽世界
        他的插件用的也是lua。
    仙剑奇侠传五
        解压游戏到资源目录可以看到游戏到脚本全部是使用Lua语言编写的。

  • 相关阅读:
    "Hello world" of ML
    数据读进set,进行后处理
    从csv文件读取数据到二维vector
    logistic regression
    Probabilistic interpretation
    python3 批量管理Linux服务器 下发命令与传输文件
    Redis 主从复制、读写分离(基于docker)
    Springboot 整合Redis
    Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to 106.xx.xxx229:6379
    docker 创建redis容器以及redis命令笔记
  • 原文地址:https://www.cnblogs.com/begoogatprogram/p/4673803.html
Copyright © 2020-2023  润新知