一、Lua语言介绍

  • Lua语言从一开始​就被设计为能与C/C++及其他常用语言开发的软件集成在一起使用的语言,这种设计带来了非常多的好处:
  • 一方面, Lua语言不需要在性能、与三方软件交互等C语言已经非常完善的方面重复“造轮子”,可以直接依赖C语言实现上述特性,因而Lua语言非常精简
  • 另一方面,通过引入安全的运行时环境、自动内存管理、良好的字符串 处理能力和可变长的多种数据类型, Lua 语言弥补了C语言在非面向硬件的高级抽象能力、 动态数据结构、鲁棒性、调试能力等方面的不足
  • Lua语言强大的原因之一就在于它的标准库,​这不是偶然,毕竟扩展性本身就是 Lua语言的主要能力之一。Lua语言中的许多特性为扩展性的实现提供了支持:动态类型使得一定 程度的多态成为了可能,自动内存管理简化了接口的实现(无须关心内存的分配/释放及处 理溢出),作为第一类值的函数支持高度的泛化,从而使得函数更加通用
  • Lua语言除了是一门可扩展的语言外,还是一门胶水语言(glue language)​。Lua 语言支 持组件化的软件开发方式,通过整合已有的高级组件构建新的应用。这些组件通常是通过 C/C++等编译型强类型语言编写的, Lua语言充当了整合和连接这些组件的角色。通常,组件(或对象)是对程序开发过程中相对稳定逻辑的具体底层(如小部件和数据结构)的抽象,这些逻辑占用了程序运行时的大部分 CPU 时间,而产品生命周期中可能经常发生变化的逻辑则可以使用 Lua 语言来实现。当然,除了整合组件外 Lua 语言也可以用来适配和改 造组件,甚至创建全新的组件
  • Lua 语言并非这个世界上唯一的脚本语言,还有许多其他的脚本语言提供了类似的能力尽管如此,​ Lua语言的很多特性使它成为解决许多问题的首选,这些特性如下:
  • 可扩展: ​Lua 语言具有卓越的可扩展’性 Lua 的可扩展性好到很多人认为 Lua 超越了编 程语言的范畴,其甚至可以成为一种用于构建领域专用语言( Domain-Specific Language,DSL )的工具包 Lua 从一开始就被设计为可扩展的,既支持使用 Lua 语言代码来扩展, 也支持使用外部的C语言代码来扩展。在这一点上有一个很好的例证: Lua 语言的大部分基础功能都是通过外部库实现的。我们可以很容易地将 Lua与C/C++、Java、C#和Python等结合在一起使用
  • 简明: ​Lua 语言是一门精简的语言。尽管它本身具有的概念并不多,但每个概念都很强大。这样的特性使得 Lua 语言的学习成本很低,也有助于减小其本身的大小(其包含所有标准库的 Linux 64 位版本仅有 220 KB)
  • 高效:​Lua 语言的实现极为高效。独立的性能测试说明 Lua 语言是脚本语言中最快的语言之一
  • 可移植:​Lua 语言可以运行在我们昕说过的几乎所有平台之上, 包括所有的 UNIX 操作系统(Linux FreeBSD等)、 Window、Android、iOS、OS X、IBM大型机、游戏终端( PlayStation、Xbox、Wii 等) 、微处理器(如 Arduino )等、针对所有这些平台的 源码本质上是一样的, Lua 语言遵循 ANSI(ISO)C标准,并未使用条件编译来对不同平台进行代码的适配。因此,当需要适配新平台时,只要使用对应平台下的 ISO C 编译器重新编译 Lua 语言的源码就可以了

二、Lua解释器的安装

  • Lua解释器是用来运行Lua程序的,此处我们以ubuntu为例,来安装Lua解释器
  • 可以到​​http://www.lua.org/ftp/​​中下载最新的Lua版本(此处我们以Lua 5.4.0为例)


安装过程

  • 第一步:​下载Lua源码包,并进入目录

wget http://www.lua.org/ftp/lua-5.4.0.tar.gz

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_程序段

  • 第二步:​解压源码包,并进入目录

tar zxf lua-5.4.0.tar.gz

cd lua-5.4.0/

ls

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_lua_02

  • 第三步:​编译

make linux test

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_Lua语言介绍_03

  • 第四步:​之后会在src目录下生成两个可执行程序lua和luac

ls src/

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_环境变量_04

  • 第五步:​安装Lua

sudo make install

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_lua_05

  • 安装完成之后:
  • 头文件保存在/usr/local/include/目录下
  • 可执行程序保存在/usr/local/bin/目录下
  • 动态库安装在/usr/local/lib/目录下
  • 还有一些内容也安装在/usr/l;ocal目录下

ls /usr/local/include/lua*

ls /usr/local/bin/lua*

ls /usr/local/lib/liblua*

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_Lua语言介绍_06

  • 第六步:​刷新动态库链接

sudo ldconfig

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_Lua语言介绍_07

  • 第七步:​查看lua安装的版本

lua -v

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_程序段_08


三、运行两个lua程序案例


演示案例1

  • 建立一个hello.lua文件,内容如下:

print("Hello World")

  • 运行效果如下:

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_Lua语言介绍_09



演示案例2

  • 下面的fact.lua程序用来求一个数的阶乘结果:

-- 定义一个计算阶乘的函数
function fact(n)
if n == 0 then
return 1
else
return fact(n-1) * n
end
end

print("enter a number:")

-- 读取一个数字
a = io.read("*n")

-- 打印结果
print(fact(a))

  • 运行效果如下:

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_环境变量_10


四、程序段

  • 我们将Lua语言执行的每一段代码(例如,一个文件或交互模式下的一行)​称为一个程序段​(Chunk),即一组命令或表达式组成的序列
  • 程序段既可以简单到只由一句表达式构成,也可以由多句表达式和函数定义(实际是赋值表达式)组成(例如计算阶乘的演示案例)
  • 程序段在大小上并没有限制,​事实上,由于Lua语言也可以被用作数据定义语言,所以几MB的程序段也很常见。Lua语言的解释器可以支持非常大的程序段

五、交互式解释器

  • 除了将源码保存为文件,然后使用lua运行之外,还可以​使用交互式模式的独立解释器


进入交互式解释器

  • 在命令行下​直接输入lua即可进入

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_Lua语言介绍_11

  • 进入之后​输入的每一条命令都会在按下回车键之后立即执行
  • 例如,我们输入下面的语句

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_环境变量_12



退出交互式解释器

  • 有两种方式退出交互式解释器:

  • 输入EOF控制符(POSIX下为ctrl+D、Windows下为ctrl+Z)

  • 或者调用操作系统的exit函数(执行os.exit())退出

  • 例如,在Linux下​输入ctrl+D退出:

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_Lua语言介绍_13

  • 或者​执行os.exit()退出

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_Lua语言介绍_14


  • 更多关于lua交互式的使用,见下面完整介绍

六、Lua解释器完整介绍

  • 下面列出了lua解释器的参数选项:
  • 所有参数都是可选的
  • 当不使用任何参数调用lua时,就进入了上面的交互式模式

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_Lua语言介绍_15


交互式Lua

  • 当不使用任何参数调用lua时,就进入了上面的交互式模式
  • 在上面已经介绍了



Lua脚本

  • lua解释器​默认安装在/usr/local/bin/目录下​,如下所示:

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_程序段_16

  • 因此,当一个脚本的开头​以"#!/usr/local/bin/lua"开始时,​这是一个​lua的脚本​,这个脚本中可以执行lua程序
  • 下面是一个​名为lua_test.sh的脚本,​内容如下:

#!/usr/local/bin/lua

print("HelloWorld")

  • 赋予其可执行权限,并运行:

chmod +x lua_test.sh

./lua_test.sh

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_环境变量_17



与老版本中的兼容

  • 从Lua 5.3版本开始,​可以直接在交互式模式下输入表达式,Lua语言会输出表达式的值​,例如

math.pi/4

a = 15

a ^ 2

a + 2

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_lua_18

  • 但是,​在Lua 5.3之前,需要在表达式前面加上一个“=”号

a = 15

= a ^ 2

= a + 2

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_程序段_19

  • 为了向下兼容,Lua 5.3之后的版本还是支持之前的语法



-e选项

  • 该选项​允许我们直接在命令行中输入代码
  • 备注:​在POSIX系统下需要使用双引号,以防止Shell错误地解析括号
  • 例如:

lua -e "print(math.sin(12))"

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_lua_20



-i选项

  • -i选项可以​让Lua解释器在执行完指定的程序段之后再进入交互模式
  • 这一选项​对于调试和手工测试很有用
  • 例如,下面是一个prog.lua程序

print("Hello World")

a = 15

  • 现在我们输入下面的命令,​让其执行完prog.lua程序再进入交互模式:

lua -i prog.lua

  • 可以看到其​打印了“Hello World”​,然后打印a,可以看到​a为15

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_程序段_21



-l选项

  • 该选项​用于加载库之后再进入交互式模式​,与-i选项有点类似
  • 例如,​下面的命令先加载lib库,然后再执行x=10的赋值语句,并最终进入交互模式,进入之后打印x可以看到我10

lua -i -llib -e "x=10"

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_环境变量_22



dofile()函数

  • 进入交互式解释器之后,可以​调用dofile()函数加载一个外部已经存在的lua文件
  • 该函数在开发阶段也很有用​。我们可以同时打开两个窗口,一个窗口使用文件编辑器编辑的代码(例如prog.lua),另一个窗口中使用交互式模式运行Lua语言解释器。当修改完代码并保存后,只要在Lua语言交互模式的提示符下执行dofile("prog.lua")就可以加载新代码
  • 例如,​下面有一个lib.lua文件,内容如下:

-- 定义了两个函数

function norm(x, y)
return math.sqrt(x^2 + y^2)
end

function twice(x)
return 2.0*x
end

  • 我们进入交互式解释器,然后在里面​调用dofile()函数让其加载lib.lua文件​的所有内容,之后就可以​调用里面的函数了

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_lua_23



;的使用

  • 如果执行一行语句之后,在末尾加上了分号(;),那么这条语句的输出不会被打印,但是这条命令被执行了
  • 例如:​输入io.flush()默认会输出"true",可以在末尾加上;让其不打印消息

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_程序段_24

  • 即使不打印消息,但是这条语句也是被执行了的

Lua:01---Lua语言介绍、运行Lua程序(lua解释器)_Lua语言介绍_25



LUA_INIT_5_4、LUA_INIT环境变量

  • lua解释器在处理参数前,会​先查找系统中名为LUA_INIT_5_4环境变量​(根据你Lua的版本而定,我的lua版本为5.4),如果查找不到​再去查找LUA_INIT环境变量
  • 如果这两个环境变量中的任意一个存在,如果:
  • 这两个环境变量的内容为@filename,那么lua解释器就会运行这个文件
  • 这两个环境变量的内容不是以@开头的,那么解释器就会认为这两个环境变量包含的是lua代码,会对其进行解释执行
  • 这些环境变量使得我们可以灵活的配置独立解释器​。例如,我们可以预先加载程序包(Package)、修改路径、定义自定义函数、对函数进行重命名或删除函数等等



lua解释器的程序参数

  • lua在运行代码前会​创建一个名为arg的表,这个表存储了所有的命令行参数​。你可以把它想象为C语言中main函数的argv数组
  • Lua语言也支持可变长参数,​可以通过可变长参数表达式来获取,在脚本文件中,表达式...表示传递给脚本的所有参数​(这些内容在后面介绍“可变长参数”的时候再介绍)
  • 例如,​下面我们需要调用lua来执行script脚本,并且给该脚本传入了3个参数a、b、c,那么
  • arg[0]=script、arg[1]=a、arg[2]=b、arg[3]=c

lua script a b c

  • 位于脚本之前的所有选项位于负数索引上,​例如:
  • arg[-3]=lua、arg[-2]=-e、arg[-1]=sin=mayj.sin、arg[0]=script、arg[1]=a、arg[2]=b、arg[3]=c

lua -e "sin=math.sin" script a b c