(6)LUA程序设计-编译执行与错误(compile 、run & error)处理

1.编译问题

----------------------------

----------------------------

首先我们谈一下编译的问题,LUA的执行,是将源代码转换成中间代码的形式执行的。

说到这里,也许会有不少人会问,LUA不是一种解释型语言,没错!LUA就是一门解释型动态语言脚本。其实区别一门语言是否为解释型语言,关键在不在于它是否被编译,而是它的编译器是否是运行时库的一部分,是否具备动态执行代码的能力。所以LUA是代码是需要被转成中间代码被LUA编译器执行的。

1.1LUA当中的常见编译函数

1.1.1 loadfile

LUA中,有dofile这样子函数,用于加载LUA代码文件,用法:dofile(filename), eg.dofile('xxx.lua');但其实dofile是调用了更深层的loadfile函数,与dofile类似,loadfile同样是用于加载编译一个代码块(chunck),但是除此之外loadfile还返回一个函数,同时如果编译出错,loadfile还会返回nil及相关错误信息。dofile调用loadfile的代码如下:

funciton dofile(filename)

local f = assert(loadfile(filename));

return f();

end

说明:1.assert用判断loadfile是否成功,有点像java/javascript里边的一个try{}catch{},用以引发错误信息。

2.dofile相对loadfile来说,每次调用,都需要重新编译一次被加载的代码块,而一次调用loadfile可以多次调用loadfile返回的函数引用。

1.1.2 loadstring

与loadfile类似,loadstirng 是用于加载lua代码块的字符串形式,并返回由该代码块组成的一个函数。

如:f = loadstring("i = i+1");

i = 0;

f() -->1

f()-->2

上面等价于

i = 0;

loadstring("i = i+1")( );-->1

loadstring("i = i+1")( );-->2

为了让错误显示得更清楚,我们可以为loadstring 的返回值加上 assert,即 assert(loadstring(s))()的形式

LUA将所以有独立的代码块都看成是一个匿名函数的函数体,而函数有可变参数这个特征(前面讲到的三大特征之一),所以loadstring函数所返回的函数,也允许传入参数。只需要在loadstirng(s)的s当中声明一个local变量用于保存可变参数,即可

f = loadstring("local xx = ... return xx "); f('hello') -- hello

------------------------------------------

注:f = loadstring('i = i+1') 基本上等价于 f = function() i = i+1 end

但是两者有极大的区别:

1.从词法域上来讲,loadstring 的方式,不涉及词法域,举例如下

i = 32

local i = 0

f = loadstring("i = i+ 1");

g = function() i=i+1 end;

f() --33

g() -- 1

2.从编译次数的角度来说,loadstring 每次调用都要重新编译一次,而function的形式,只编译一次。

1.1.3 load

与loadfile和loadstring相比,load函数有所不同。loadfile和loadstring 是分别从文件和字符串中读取程序块,但load则不同,如果加载的代码块过大,内存空间不够,用load则可以解决问题,它接收一次读取器函数,可以将一个程序块分多几读取,通过反复调用“读取器函数”,直到返回nil为止。

1.1.4 loadlib

众所周知,动态链接机制并非ansi c 标准的一部分,LUA用C编写的,不会包含无法用ANSI C实现的所有机制,但是动态链接机制除外,LUA将动态链接机制作为实现其他机制的母机制,通过动态机制,LUA可以加载任何LUA不支持的机制。

LUA加载动态链接库,主要用到函数package 下的loadlib,用法如下

local dynaLinkLibPath = ''/usr/local/lib/lua/5.0/socket.so' --linux下动态链接库后缀为so

local f = package.loadlib(path,'luaopen_socket');

package.loadlib通过指定加载库的路径,以及C函数名,返回一个LUA函数,用以被LUA代码调用。loadlib将结合我们后面要讲的require函数使用,require用于搜索指定库,loadlib用于加载搜到的库。

2.错误处理,异常封装,错误跟踪

2.1 LUA当中错误处理一般情况是

f = io.open(file);

if not f then

<error code here>

else

....

end

当然LUA提供了一个内建引发错误的函数,即上面讲到的assert函数

它接收到两个参数,第一个参数是lua的代码块,可以是一个表达式,一个函数调用的返回结果,第二个参数是一个字符串,用于提供 第一个参数代码执行时出错的提示


2.2异常封装

LUA提供一种pcall保护模式,pcall是一个函数,参数是一个函数,pcall返回两个值,第一个是函数参数是否调用成功,调用失败返回false,否则返回true.第二个参数是调用失败的错误信息。

local status ,err = pcall(function() error({code=500}) end);--可以自定义出错代码

print(err.code)--打印出错代码

2.3 错误跟踪

error()函数,可以接收一个字符串参数,用于提示出错原因,如error("the wrong string unexpected!!");,也可以接收两个参数,第一个参数用于提示出错原因,第二个参数用于表示具体出错的级别,可以跟踪错误出现的位置。举例如下:

function fuck(s)

if type(s) ~= 'string' then

error('string expected!!')

else ....

end

如果主函数调用了fuck()函数,并传入一个122number类型的数值,fuck将出错,但是并不能显示出错的层次,并不知道出错在哪里,所以将上面代码改成

function fuck(s)

if type(s) ~= 'string' then

error('string expected!!',2)

else ....

end

注:在error函数加入第二个参数2,那么出错时将提示具体出错的位置,便于调试跟踪!!!


完毕!!下节将讲解lua程序设计基础篇的最后一小节,内容也是相当重要!!也难理解!!

----------------好了---本节到此结束,下一节将讲解-(7)LUA程序设计-协同程序(coroutine)------------

LUA技术交流群,请加Q群:139315537,加入请注明来源。

(1)LUA程序设计-开篇(beginning)(2012-07-28 00:47)
(2)LUA程序设计-类型与值(type & value)(2012-07-28 23:12)
(3)LUA程序设计-表达式与语句(expression & statement)(2012-07-29 22:51)


(4)LUA程序设计-函数及深入理解(function)(2012-08-03 23:00)


(5)LUA程序设计-迭代器(state iterator & stateless iterator)(2012-08-06 23:05)
(6)LUA程序设计-编译执行与错误(compile 、run & error)处理(2012-08-11 00:05)
(7)LUA程序设计-协同程序(coroutine)(2012-09-01 00:06)

你可能感兴趣的:(compile)