ngin Finding Everything About Nginx Here

编写lua扩展模块

发表于 2015-06-28 阅读数 3048

lua本身以小巧精致著称,但同是又提供良好机制以支持开发者编写其扩展模块。本文将全面介绍如何编写lua扩展模块,让您根据业务需要轻松实现自己的扩展模块。由于每个版本的实现方式有点出入,本文将基于5.3。

1、什么是模块

模块就是提供服务的任何东西,可以是函数、类、或其它。在lua里有两种方式体现:

a、函数形式

--- foo.lua ---

function foo()

    print("foo func");

end

--- test.lua ---

require("foo");

foo();

b、对象形式

--- bar.lua ---

local bar = {};

function bar.say()

    print("bar say")

end

return bar; -- 注意这里要返回前面定义的对象

--- test.lua ---

bar = require("bar");

bar.say();

第一种是非常常见的形式,很多语言都支持这种方式。第二种方式在代码组织可能稍微好点,有模块或类的影子。

2、lua的模块查找机制

lua在模块的使用上非常简单,只需要require模块名。但是它是如何找到模块文件的呢?

运行下面这行代码:

require("m"); -- 这是一个不存在的模块

------ 输出 ------

no field package.preload['m']

no file '/usr/local/share/lua/5.3/m.lua'

no file '/usr/local/share/lua/5.3/m/init.lua'

no file '/usr/local/lib/lua/5.3/m.lua'

no file '/usr/local/lib/lua/5.3/m/init.lua'

no file './m.lua'

no file './m/init.lua'

no file '/usr/local/lib/lua/5.3/m.so'

no file '/usr/local/lib/lua/5.3/loadall.so'

no file './m.so'

目录:/usr/local/share/lua/5.3, /usr/local/lib/lua/5.3, ./(当前)

文件:m.lua和init.lua

一旦找到就当作要被引入的文件。

另外你也可以指定模块的查找路径:

package.path = "xxx";

这个值可以包含一个特殊的字符'?',相当于require函数的值。举例,当前目录为/tmp/test,我们创建一个目录/tmp/test/lib,专门放模块文件。模块文件为/tmp/test/lib/foo.lua,现在我们要引入它。

package.path = package.path .. "/tmp/test/lib/?.lua";

require("foo");

3、集思广义

很多时候我们以第二种方式组织代码,因为所有模块的功能都封装在模块对象里。

--- bar.lua ---

local bar = {};

function bar.say()

    print("bar say")

end

function bar.greet()

    print("bar greet")

end

return bar;

--- test.lua ---

bar = require("bar");

bar.say();

bar.greet();

如果换成第一种方式,但在命名上稍加改动。

--- bar.lua ---

function bar_say()

    print("bar say")

end

function bar_greet()

    print("bar greet")

end

--- test.lua ---

require("bar");

bar_say();

bar_greet();

其实在本质上都遵守一个原则:服务以'模块+功能'方式提供。这点在nginx的源码上体现的淋漓尽致。