教程 > Lua 教程 > Lua 基础 阅读:45

Lua 模块和包

什么是模块

模块就像一个可以使用 require 加载的库,并且有一个包含表的全局名称。 该模块可以包含许多函数和变量。 所有这些函数和变量都包含在表中,该表充当命名空间。 此外,表现良好的模块具有必要的规定,可以在需要时返回此表。


Lua 模块的特点

模块中表的使用以多种方式帮助我们,使我们能够像操作任何其他 Lua 表一样操作模块。 由于能够操作模块,它提供了其他语言需要特殊机制的额外功能。 由于 Lua 中模块的这种自由机制,用户可以通过多种方式调用 Lua 中的函数。 其中一些如下所示。

-- 假设我们有一个模块 printFormatter
-- 还有 printFormatter 有一个函数 simple Format(arg)
-- 方法 1
require "printFormatter"
printFormatter.simpleFormat("test")

-- 方法 2
local formatter = require "printFormatter"
formatter.simpleFormat("test")

-- 方法 3
require "printFormatter"
local formatterFunction = printFormatter.simpleFormat
formatterFunction("test")

在上面的示例代码中,我们可以看到 Lua 中的编程是多么灵活,无需任何特殊的附加代码。


require 函数

Lua 提供了一个名为 require 的高级函数来加载所有必要的模块。 它保持尽可能简单,以避免在模块上加载太多信息。 require 函数只是将模块假定为定义一些值的代码块,这些值实际上是函数或包含函数的表。

示例

让我们考虑一个简单的例子,其中一个函数具有数学函数。 我们称这个模块为 mymath,文件名为 mymath.lua。 文件内容如下

mymath.lua

local mymath =  {}

function mymath.add(a,b)
   print(a+b)
end

function mymath.sub(a,b)
   print(a-b)
end

function mymath.mul(a,b)
   print(a*b)
end

function mymath.div(a,b)
   print(a/b)
end

return mymath    

现在,为了在另一个文件中访问这个 Lua 模块,比如 moduletutorial.lua,我们需要使用以下代码段。

moduletutorial.lua

mymathmodule = require("mymath")
mymathmodule.add(10,20)
mymathmodule.sub(30,20)
mymathmodule.mul(10,20)
mymathmodule.div(30,20)

为了运行此代码,我们需要将两个 Lua 文件放在同一目录中,或者我们可以将模块文件放在包路径中,它需要额外的设置。 当我们运行上述程序时,我们将得到以下输出。

30
10
200
1.5

要记住的事情

  • 将模块和我们运行的文件放在同一目录中。
  • 模块名称和它的文件名应该相同。
  • 最好的做法是为 require 函数返回模块,因此即使我们可以在其他地方找到其他类型的实现,也应该最好按照上面所示的方式实现该模块。

旧的实现模块的方式

现在让我以旧方式重写相同的示例,它使用 package.seeall 类型的实现。 这在 Lua 版本 5.1 和 5.0 中使用。 mymath 模块如下所示。

mymath.lua

module("mymath", package.seeall)

function mymath.add(a,b)
   print(a+b)
end

function mymath.sub(a,b)
   print(a-b)
end

function mymath.mul(a,b)
   print(a*b)
end

function mymath.div(a,b)
   print(a/b)
end

moduletutorial.lua 中模块的用法如下所示。

moduletutorial.lua

require("mymath")
mymath.add(10,20)
mymath.sub(30,20)
mymath.mul(10,20)
mymath.div(30,20)

当我们运行上面的代码时,我们将得到相同的输出。许多使用 Lua 进行编程的 SDK(如 Corona SDK)已弃用此功能。


C 包

Lua和C是很容易结合的,使用 C 为 Lua 写包。

与Lua中写包不同,C包在使用以前必须首先加载并连接,在大多数系统中最容易的实现方式是通过动态连接库机制。

Lua在一个叫loadlib的函数内提供了所有的动态连接的功能。这个函数有两个参数:库的绝对路径和初始化函数。所以典型的调用的例子如下:

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

loadlib 函数加载指定的库并且连接到 Lua,然而它并不打开库(也就是说没有调用初始化函数),反之他返回初始化函数作为 Lua 的一个函数,这样我们就可以直接在Lua中调用他。

如果加载动态库或者查找初始化函数时出错,loadlib 将返回 nil 和错误信息。我们可以修改前面一段代码,使其检测错误然后调用初始化函数:

local path = "/usr/local/lua/lib/libluasocket.so"
-- 或者 path = "C:\\windows\\luasocket.dll",这是 Window 平台下
local f = assert(loadlib(path, "luaopen_socket"))
f()  -- 真正打开库

一般情况下我们期望二进制的发布库包含一个与前面代码段相似的 stub 文件,安装二进制库的时候可以随便放在某个目录,只需要修改 stub 文件对应二进制库的实际路径即可。

将 stub 文件所在的目录加入到 LUA_PATH,这样设定后就可以使用 require 函数加载 C 库了。

查看笔记

扫码一下
查看教程更方便