English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Lua 模块与包

Ein Modul ähnelt einer Bibliothek, von Lua 5.1 Zunächst hat Lua ein Standardmodulmanagementmechanismus hinzugefügt, mit dem allgemeine Code in einer Datei gespeichert werden kann, um ihn als API-Schnittstelle an anderen Orten aufzurufen. Dies fördert die Wiederverwendung von Code und verringert die Kopplung von Code.

Lua hat ein Standardmodulmanagementmechanismus eingeführt, mit dem allgemeine Code in einer Datei gespeichert werden kann, um ihn als API-Schnittstelle an anderen Orten aufzurufen. Dies fördert die Wiederverwendung von Code und verringert die Kopplung von Code.

-- Dateiname module.lua
-- Ein Modul namens module definieren
module = {}
 
-- Konstante definieren
module.constant = "Das ist eine Konstante"
 
-- Funktion definieren
function module.func1(),
    io.write("Das ist eine öffentliche Funktion!\n")
end
 
local function func2(),
    print("Das ist eine private Funktion!")
end
 
function module.func3(),
    func2(),
end
 
return module

Wie aus dem obigen Beispiel hervorgeht, besteht die Struktur eines Moduls aus einer Tabelle, daher können Konstanten oder Funktionen im Modul wie Elemente einer Tabelle behandelt und aufgerufen werden.

Die obige func2 Deklarierte lokale Variablen in einem Programmblock stellen private Funktionen dar, daher können diese privaten Funktionen im Modul nicht von außen aufgerufen werden. Es muss über öffentliche Funktionen im Modul aufgerufen werden.

require Funktion

Lua bietet eine Funktion namens require, um Module zu laden. Um ein Modul zu laden, genügt es, diese einfach aufzurufen. Zum Beispiel:

require("<Modulname>")

oder

require "<Modulname>"

Nach dem Ausführen von require wird eine Tabelle zurückgegeben, die aus Modulkonstanten oder Funktionen besteht, und eine globale Variable, die diese Tabelle enthält, wird ebenfalls definiert.

test_module.lua Datei

-- test_module.lua Datei
-- The module module mentioned above is module.lua
require("module")
 
print(module.constant)
 
module.func3(),

The result of executing the above code is:

This is a constant
This is a private function!

Or define an alias variable for the loaded module for convenience:

test_module2.lua file

-- test_module2.lua file
-- The module module mentioned above is module.lua
-- Alias variable m
local m = require("module")
 
print(m.constant)
 
3(),

The result of executing the above code is:

This is a constant
This is a private function!

Loading mechanism

For custom modules, the module file does not have to be placed in any file directory. The require function has its own file path loading strategy, and it will try to load the module from Lua files or C program libraries.

The require function is used to search for the path of Lua files, which is stored in the global variable package.path. When Lua starts, it initializes this environment variable with the value of the environment variable LUA_PATH. If this environment variable is not found, it uses a default path defined at compile time to initialize.

Of course, if there is no LUA_PATH environment variable, you can also set it manually. Open the .profile file in the current user's root directory (create it if it does not exist, or open the .bashrc file), for example, set "~/lua/" The path is added to the LUA_PATH environment variable:

#LUA_PATH
export LUA_PATH="~/lua/?.lua;;"

File paths are separated by ";", and the last 2 A ";;" represents adding the new path after the original default path.

Next, update the environment variable parameters to take effect immediately.

source ~/.profile

At this point, assume that the value of package.path is:

/Users/dengjoe/lua/?.lua;./?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/lib/lua/5.1/?.lua;/usr/local/lib/lua/5.1/?/init.lua

Then, when calling require("module"), it will try to open the following directory to search for the target.

/Users/dengjoe/lua/module.lua;
./module.lua
/usr/local/share/lua/5.1/module.lua
/usr/local/share/lua/5.1/module/init.lua
/usr/local/lib/lua/5.1/module.lua
/usr/local/lib/lua/5.1/module/init.lua

If the target file has been searched for, package.loadfile will be called to load the module. Otherwise, it will look for C program libraries.

The file path for the search is obtained from the global variable package.cpath, which is initialized by the environment variable LUA_CPATH.

The search strategy is the same as above, but now it searches for files of type so or dll. If it finds them, require will load them using package.loadlib.

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 库了。