• LUA的编译、环境等


    Lua的环境、编译等

     

    Lua命令行

    lua命令行选项:

    -i:进入交互式

    -e:执行lua代码

    -l:加载库文件

    例如使用下面的命令启动lua解释器,可以重新定义lua提示符。


    lua -i -e "_PROMPT=' try>'"

    在交互模式下,如果要打印任何表达式的值,可以用等号开头,并跟随一个表达式,例如:

    > a="hello" .. "world"
    > =a
    helloworld
    > =math.sin(180)
    -0.80115263573383
    > 

    lua解释器执行其参数前,会先查找一个名为LUA_INIT的环境变量:

    如果找到这个变量,并且其内容为“@filename”,那么解释器会先执行这个文件; 如果LUA_INIT不是以@开头,则作为Lua代码执行。

    如下面的示例,将LUA_INIT定义为"@a.lua",然后启动lua解释器,自动加载了a.lua文件。

    root@chenqi-PC:/home/chenqi/studio/test# cat a.lua 
    #!/usr/bin/lua
    
    print("hello world")
    
    root@chenqi-PC:/home/chenqi/studio/test# export LUA_INIT="@a.lua"
    root@chenqi-PC:/home/chenqi/studio/test# lua
    hello world
    Lua 5.2.2  Copyright (C) 1994-2013 Lua.org, PUC-Rio
    > 

    解释器在运行脚本前,会用所有的命令行参数创建一个名为arg的table,例如test.lua源文件内容如下,

    for i,v in pairs(arg) do
        print(string.format("arg[%d]=%s", i,v))
    end

    执行后,打印出所有的参数:

    root@chenqi-PC:/home/chenqi/studio/test# lua -e "sin=math.sin" test.lua a b
    arg[1]=a
    arg[2]=b
    arg[-1]=sin=math.sin
    arg[-3]=lua
    arg[-2]=-e
    arg[0]=test.lua

    环境 

    Lua执行的每段代码,例如一个源文件,或在交互模式中输入的一行代码,都称为一个chunk。

    一个chunk可以简单到只包含一条语句,也可以由若干条不同的语句及函数定义构成。

    Lua中定义的变量默认都是全局变量,要删除一个全局变量,只需将其赋值为nil。

    a=10
    print(a)        --> 10
    a=nil
    print(a)        --> nil

    可以使用关键字local声明局部变量,局部变量的作用域仅限于声明它们的那个block,

    一个block可以是一个控制结构的执行体,或者是一个函数的执行体,或者是一个chunk。

    一个例子:

    local x=0 
    
    for i=1,4 do
        local x=i+1
        print(x)    --> 2,3,4,5
    end
    
    print(i)  --> nil
    print(x)  --> 0

    刚才提到,在交互模式下,每一行代码都是一个chunk,例如:

    > a=3
    > =a
    3
    > local b=3
    > =b
    nil
    > 

    上面的例子中,局部变量b在下一行代码(一个新的chunk)中就消失了。

    注意:local同样也可以用来修饰函数,从而定义一个局部函数。

    lua中应该尽可能使用局部变量,可以避免将一些无用的名称引入全局环境(global environment);

    此外,访问局部变量比访问全局变量更快,Lua的全局变量是放在一个table中的,即_G,例如:

    chenqi = 12
    local cq = 21
    
    print(_G['chenqi']) -- 12
    print(_G['cq'])     -- nil

    最后,一个局部变量通常会随着作用域的结束而消失,这样垃圾收集器可以及时释放内存。

    在lua中,有一种习惯的写法是:

    local foo=foo

    这句代码的意义是创建局部变量foo,并用全局变量foo的值对它初始化,如果后续其它函数改变了全局foo的值,那么这里可以先将它的值保存起来。

    这种写法的另一个作用就是加速在当前作用域中对foo的访问。

    全局变量

    访问具有动态名字的全局变量:

    _G['company'] = {name='sina' }
    
    function getfield(f)
        local v = _G
        for w in string.gmatch(f, "[%w_]+") do
            v = v[w]
        end
        return v
    end 
    
    print(_G['company.name'])           -- nil
    print(getfield('company.name'))     -- sina 

    编译

    loadfile

    local func = loadfile("mode_name")
    
    func()

    loadfile 函数会将代码编译成中间码,并且将编译后的chunk作为一个函数返回,而不执行代码。

    另外,loadfile不会抛出错误信息,而是返回错误码。

    loadstring

    loadstring 函数与loadfile类似,不过它不是从文件里读入chunk,而是从一个字符串中读入,例如:

    f = loadstring("i=i+1")
    
    i = 0
    f();print(i)        -- 1
    f();print(i)        -- 2

    Lua把每一个chunk都作为一个匿名函数处理,并且该匿名函数还具有可变长实参。例如:

    loadstring("a=1")返回的结果等价于表达式:function(...) a=1 end

    loadfile和loadstring都是编译代码,然后将编译结果作为一个函数返回。
    loadfile和loadstring都不会引发错误,只是返回nil和错误消息:

    print(loadstring("i i "))
    -- nil     [string "i i "]:1: '=' expected near 'i'

     loadstring总是在全局环境中编译它的字符串,如下面的例子中,函数g操作了局部的i,函数f操作的却是全局的i。

    i = 32
    local i = 0
    
    f = loadstring("i=i+1; print(i)")
    g = function() i=i+1; print(i) end
    
    f()     -- 33
    g()     -- 1

    loadstring常用于执行外部代码,例如:

    print "enter your expression: "
    local l = io.read()
    local func = assert(loadstring("return " .. l)) 
    print("result is: " .. func())

    dofile

    dofile("model_name.lua")

    dofile 函数读入文件、编译,然后执行,它实际上是对loadfile的封装:

    function dofile(filename)
    
        local f = assert(loadfile(filename))
    
        return f()
    
    end

      

     

    动态链接

    Lua支持加载动态链接库,如下

    local path = "/usr/local/lib/lua/5.1/socket.so"
    local f = package.loadlib(path, "luaopen_socket")

    如果在加载库时发生错误,loadlib返回nil及一条错误消息。

    loadlib是一个非常底层的函数,必须提供库的完整路径及正确的函数名。通常使用require来加载C程序块,这个函数库会搜索指定的库,然后用loadlib来加载库,并返回初始化函数,这个初始化函数应将库中提供的函数注册到Lua中。

    require

    require("model_name")

    require 函数载入model_name.lua文件,载入的同时直接执行该文件,注意:只有第一次载入的时候会去执行。

    与dofile不同的是,require提供了2个功能:

    1、搜索目录加载文件;

    2、判断文件是否已加载,避免重复加载。

    指定搜索lua模块的路径:

    package.path = '/usr/local/share/lua/5.1/?.lua;/home/resty/?.lua;' 

    指定搜索so模块的路径:

    package.cpath = '/usr/local/lib/lua/5.1/?.so;'


     错误与异常处理

    Lua所遇到的任何未预期条件都会引发一个错误。例如,当试图将两个非数字的值相加、索引一个不是table的值,等。
    Lua也可以通过调用error函数显式地引发一个错误,例如:

    local n = 'a'
    if not n then error("invalid n") end
    
    n = nil
    assert(n, "invalid n")

    assert函数的作用是判断第一个参数是否true,如果不是则自动调用error函数引发错误。

    error用来抛出异常,而捕获异常需要使用pcall函数。

    pcall函数以一种“保护模式”来调用它的第一个参数,因此pcall可以捕获函数执行中的任何错误。
    如果没有发生错误,pcall会返回true及函数调用的返回值;否则,返回false及错误消息。

    local status, err = pcall(function() error({code=121}) end)
    print(status, err.code)  -- false 121
    
    local status, ret = pcall(function() return 'ok' end)
    print(status, ret)     -- true ok

    注意:这里error函数的参数可以是任意类型,而不仅仅是字符串。

    error函数的第一个参数用于表达错误消息,事实上,它还有第二个参数,用于指出应由调用层级中的哪个层(level)来报告当前的错误,也就是说明谁应该为错误负责。

    function foo(str)
        if type ~= "string" then 
            error("string expected", 2)
        end 
    
        print(str)
    end
    
    foo(12)

    输出错误信息:

    /usr/local/bin/lua: ./test.lua:13: string expected
    stack traceback:
            [C]: in function 'error'
            ./test.lua:7: in function 'foo'
            ./test.lua:13: in main chunk
            [C]: ?
  • 相关阅读:
    ssh
    ssh免密码登陆
    滑雪[dp]
    Help Jimmy[dp]
    动态规划 [子序列问题]
    最佳加法表达式 [dp]
    求排列的逆序数[归并排序]
    输出前m大个数,时间复杂度O(n+mlog(m)) [快排]
    不会递归?五道例题教你如何递归
    函数模板的琐碎笔记
  • 原文地址:https://www.cnblogs.com/chenny7/p/3634469.html
Copyright © 2020-2023  润新知