zoukankan      html  css  js  c++  java
  • 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语言编写的。

  • 相关阅读:
    数据绑定表达式语法(Eval,Bind区别)
    使用博客园的第一件事 自定义主题
    sql2000 跨服务器复制表数据
    使用UpdatePanel 局部刷新出现中文乱码的解决方法!!
    MMC不能打开文件MSC文件
    sql 日期 、时间相关
    loaded AS2 swf call function in AS3 holder
    Rewrite the master page form action attribute in asp.net 2.0
    100万个不重复的8位的随机数
    flash 中实现斜切变型
  • 原文地址:https://www.cnblogs.com/begoogatprogram/p/4673803.html
Copyright © 2011-2022 走看看