lua快速入门 —— 编译执行与错误
本文最后更新于:2020年1月31日 晚上
概览:
参照书籍:《Lua程序设计(第二版)》
Lua版本:Lua 5.3.5
编译
Lua是一种解释型语言,但Lua允许在运行源代码前,先将源代码预编译为一种中间形式。
区别解释型语言的主要特征并不在于是否能编译它们,而是在于编译器是否是语言运行时库的一部分,即是否有能力(并轻易地)执行动态生成的代码。
Lua中的 dofile函数
,用于运行Lua代码块
1 |
|
但是实际上,loadfile函数
才是做了真正核心的工作。loadfile从一个文件加载Lua代码块,但它并不运行代码块,而是只编译代码,然后将编译结果作为一个函数返回。
1 |
|
与dofile不同的还有loadfile不会引发错误,它只是返回错误值并不处理错误。
1 |
|
上述代码中,如果loadfile失败,那么assert就会引发一个错误。
dofile在一次调用中做完了所有的事,而loadfile更加的灵活,比如需要多次运行一个文件,只需要多次使用loadfile的返回结果就可以了。
除此之外还有一个类似的loadstring函数,用于去执行外部代码。不过 loadstring在lua5.2中已经被弃用了 。
动态链接机制
Lua通常不会包含任何无法通过ANSI C来实现的机制,但是动态链接有些意外,因为ANSI C标准没有动态链接。
可以将动态链接视为其他机制的母机制,只要拥有它,就可以动态加载任何其他不在Lua中的机制了。
要检测某一平台是否支持动态链接机制,只需要在Lua命令行中运行
print(package.loadlib("a","b"))
,然后观察执行结果,如果报告不存在指定文件,就说明该平台具有动态链接机制。否则会有错误消息提示或未安装此机制。
Lua提供了所有的动态连接的功能都在一个叫package.loadlib
的函数内。这个函数有两个参数:动态库的完整路径和一个函数名称。所以典型的调用的例子如下:
1 |
|
loadlib函数加载指定的库并且连接到Lua,然而它并不打开库(也就是说没有调用初始化函数),反之他返回初始化函数作为Lua的一个函数,这样我们就可以直接在Lua中调用他。如果加载动态库或者查找初始化函数时出错,loadlib将返回nil和错误信息。
通常使用require来加载C程序库,这个函数会搜索指定的库,然后用loadlib来加载库,并返回初始化函数。这个初始化函数应将库中提供的函数注册到Lua中,就好像一段Lua代码定义了其他的函数一样。
错误
Lua经常作为扩展语言嵌入在别的应用中,所以不能当错误发生时简单的崩溃或者退出。相反,当错误发生时Lua结束当前的chunk并返回到应用中。
Lua提供了内建的assert函数
来处理错误
1 |
|
assert函数检查其第一个参数是否为true,若为true,则简单的返回该参数,否则(即false或者nil)就会引发一个错误。它的第二个参数是一个可选的信息字符串,当第一个参数为false时,assert会以第二个参数为错误信息抛出。
另:assert总会先处理两个参数(即如果参数需要计算就会进行计算),然后才调用函数。
当一个函数遭遇了一种未预期的状况(即异常时),它可以采取两种基本的行为:返回错误代码(通常时nil)**或者引发一个错误(调用error)**。
在这两种选择之间并没有固定的法则,通常的原则是:易于避免的异常应引发一个错误,否则应返回错误代码。
对于程序逻辑上能够避免的异常,以抛出错误的方式处理之,否则返回错误代码。——《Lua程序设计第一版》
Lua进行错误处理
如果想要处理错误,必须使用函数pcall来包装需要执行的代码。
第一步:将这段代码封装在一个函数内
1 |
|
第二步:使用pcall调用这个函数
1 |
|
当然也可以用匿名函数的方式调用pcall:
1 |
|
pcall函数会以一种“保护模式(protected mode)”来调用它得第一个参数,因此pcall可以捕获函数执行中的错误。如果没有发生错误,那么pcall会返回true以及函数调用的返回值,否则返回false以及错误消息。
错误信息不一定仅为字符串(下面的例子是一个table),传递给error的任何信息都会被pcall返回:
1 |
|
这种机制提供了强大的能力,足以应付Lua中的各种异常和错误情况。我们通过error抛出异常,然后通过pcall捕获之,而错误消息则可以标识出错误的类型或内容。
错误消息
通常情况下我们使用字符串来描述错误信息,如果遇到内部错误(比如对一个非table的值使用索引下标访问)Lua将自己产生错误信息,否则Lua使用传递给error函数的参数作为错误信息。
而error函数还有第二个附加参数level,来指明是调用层级中的哪一层的error()函数来报告当前错误。
1 |
|
追溯(traceback)
当错误发生的时候,我们常常希望了解详细的信息,而不仅是错误发生的位置。若能了解到“错误发生时的栈信息”就好了,但pcall返回错误信息时,已经释放了保存错误发生情况的栈信息。
因此,若想得到tracebacks,我们必须在pcall返回以前获取。Lua提供了xpcall
来实现这个功能,xpcall接受两个参数:调用函数、错误处理函数。当错误发生时,Lua会在栈释放以前调用错误处理函数,因此可以使用debug库收集错误相关信息。有两个常用的debug处理函数:debug.debug和debug.traceback,前者给出Lua的提示符,你可以自己动手察看错误发生时的情况;后者通过traceback创建更多的错误信息,也是控制台解释器用来构建错误信息的函数。你可以在任何时候调用debug.traceback获取当前运行的traceback信息:
1 |
|
else …
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!