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

Lua Modules and Packages

Modules are similar to encapsulated libraries, from Lua 5.1 At first, Lua added a standard module management mechanism, which allows some common code to be placed in a file and called from other places in the form of an API interface, which is conducive to code reuse and reducing code coupling.

Lua modules are tables composed of known elements such as variables and functions. Therefore, creating a module is very simple: create a table, put the constants and functions you need to export into it, and return the table at the end. The following is the code format for creating a custom module module.lua:

-- File name is module.lua
-- Define a module named module
module = {}
 
-- Define a constant
module.constant = "This is a constant"
 
-- Define a function
function module.func1()
    io.write("This is a public function!\n")
end
 
local function func2()
    print("This is a private function!")
end
 
function module.func3()
    func2()
end
 
return module

From the above, we can see that the structure of the module is a table structure, so you can operate and call the constants or functions in the module in the same way as you would with elements in a table.

The above func2 Local variables declared in a program block, which means a private function, so it cannot be accessed from outside the module. You must call this private function within the module by using the public functions of the module.

require function

Lua provides a function named require to load modules. To load a module, you just need to call it. For example:

require("<module_name>")

or

require "<module_name>"

After executing require, it will return a table consisting of module constants or functions, and it will also define a global variable containing this table.

test_module.lua file

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

The execution result of the above code is:

! A constant!
! A private function!

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

test_module2.lua file

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

The execution result of the above code is:

! A constant!
! 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 path used by require to search for Lua files 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 the 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, add "~/lua/" Add the path 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

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 through 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 one, require will load it using package.loadlib.

C Package

Lua and C are easy to combine, using C to write packages for Lua.

Unlike writing packages in Lua, C packages must be loaded and connected before use, and the easiest way to implement this in most systems is through the dynamic linking library mechanism.

Lua provides all the dynamic linking features within a function called loadlib. This function has two parameters: the absolute path of the library and the initialization function. So a typical call example is as follows:

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

The loadlib function loads the specified library and connects to Lua, but it does not open the library (that is, it does not call the initialization function), instead it returns the initialization function as a function of Lua, so we can call it directly in Lua.

If there is an error loading the dynamic library or finding the initialization function, loadlib will return nil and an error message. We can modify the previous code to detect errors and then call the initialization function:

local path = ""/usr/local/lua/lib/libluasocket.so
-- Or path = "C:\\windows\\luasocket.dll", this is under the Windows platform
local f = assert(loadlib(path, "luaopen_socket"))
f()  -- Open the library truly

Generally, we expect the binary distribution libraries to include a stub file similar to the previous code section. When installing binary libraries, you can place them in any directory, just modify the actual path of the stub file corresponding to the binary library.

Add the directory containing the stub file to LUA_PATH, after this setting, you can use the require function to load C libraries.