Modules et packages Lua


Un module est similaire à une bibliothèque de packages. À partir de Lua 5.1, Lua a ajouté un mécanisme de gestion de module standard, qui vous permet de mettre du code commun dans un fichier et de l'appeler à d'autres endroits sous la forme de une interface API propice à la réutilisation du code et à la réduction du couplage de code.

Le module de Lua est un tableau composé d'éléments connus tels que des variables et des fonctions, donc créer un module est très simple, il suffit de créer un tableau, puis d'y mettre les constantes et fonctions qui doivent être exportées, et enfin retourner la table C'est tout. Ce qui suit est la création d'un module personnalisé module.lua. Le format du code de fichier est le suivant :

-- 文件名为 module.lua
-- 定义一个名为 module 的模块
module = {}
 
-- 定义一个常量
module.constant = "这是一个常量"
 
-- 定义一个函数
function module.func1()
    io.write("这是一个公有函数!\n")
end
 
local function func2()
    print("这是一个私有函数!")
end
 
function module.func3()
    func2()
end
 
return module

Comme le montre ce qui précède, la structure du module est une structure de table, vous pouvez donc opérer. le module appelant tout comme les éléments de la constante ou de la fonction appelante.

La func2 ci-dessus est déclarée comme variable locale du bloc de programme, ce qui signifie qu'elle représente une fonction privée. Par conséquent, cette fonction privée dans le module n'est pas accessible de l'extérieur et doit être appelée via la fonction publique. dans le module.


fonction require

Lua fournit une fonction appelée require pour charger les modules. Pour charger un module, appelez-le simplement. Par exemple :

require("<模块名>")

ou

require "<模块名>"

Après l'exécution de require, une table composée de constantes ou de fonctions de module sera renvoyée, et une variable globale contenant la table sera également définie.

-- test_module.lua 文件
-- module 模块为上文提到到 module.lua
require("module")
 
print(module.constant)
 
module.func3()

Le résultat de l'exécution du code ci-dessus est :

这是一个常量
这是一个私有函数!

Ou définissez une variable d'alias pour le module chargé pour un appel facile :

-- test_module2.lua 文件
-- module 模块为上文提到到 module.lua
-- 别名变量 m
local m = require("module")
 
print(m.constant)
 
m.func3()

Le résultat de l'exécution du code ci-dessus est :

这是一个常量
这是一个私有函数!

Mécanisme de chargement

Pour les modules personnalisés, le fichier du module n'a pas d'importance dans le répertoire de fichiers dans lequel il est placé. La fonction require a sa propre stratégie de chargement de chemin de fichier. Elle essaiera de le faire. chargez-le à partir d’un fichier Lua ou d’une bibliothèque C.

require Le chemin utilisé pour rechercher les fichiers Lua est stocké dans la variable globale package.path. Au démarrage de Lua, cette variable d'environnement sera initialisée avec la valeur de la variable d'environnement LUA_PATH. Si la variable d'environnement n'est pas trouvée, un chemin par défaut défini au moment de la compilation est utilisé pour l'initialisation.

Bien sûr, s'il n'y a pas de variable d'environnement LUA_PATH, vous pouvez également personnaliser les paramètres et ouvrir le fichier .profile dans le répertoire racine de l'utilisateur actuel (créez-le s'il n'existe pas, ou ouvrez le fichier .bashrc ), par exemple, modifiez "~/lua /" Ajoutez le chemin de la variable d'environnement LUA_PATH :

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

Le chemin du fichier est séparé par ";", et les deux derniers ";;" signifient que le nouveau path est suivi du chemin par défaut d’origine.

Ensuite, mettez à jour les paramètres des variables d'environnement afin qu'elles prennent effet immédiatement.

source ~/.profile

Supposons que la valeur de package.path est :

/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

Ensuite, lorsque require("module") est appelé, il essaiera d'ouvrir le répertoire de fichiers suivant pour rechercher la cible.

/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

Si le fichier cible est trouvé, package.loadfile sera appelé pour charger le module. Sinon, il va dans la bibliothèque C.

Le chemin du fichier recherché est obtenu à partir de la variable globale package.cpath, et cette variable est initialisée via la variable d'environnement LUA_CPATH.

La stratégie de recherche est la même que ci-dessus, sauf que maintenant la recherche porte sur des fichiers de type so ou dll. S'il est trouvé, require le chargera via package.loadlib.


Package C

Lua et C sont faciles à combiner. Utilisez C pour écrire des packages pour Lua.

Contrairement aux packages écrits en Lua, les packages C doivent d'abord être chargés et connectés avant utilisation. Dans la plupart des systèmes, le moyen le plus simple de l'implémenter consiste à utiliser le mécanisme de bibliothèque de liens dynamiques.

Lua fournit toutes les fonctions de liaison dynamique dans une fonction appelée loadlib. Cette fonction prend deux paramètres : le chemin absolu vers la bibliothèque et la fonction d'initialisation. Ainsi, un exemple d'appel typique est le suivant :

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

La fonction loadlib charge la bibliothèque spécifiée et se connecte à Lua. Cependant, elle n'ouvre pas la bibliothèque (c'est-à-dire qu'elle n'appelle pas la fonction d'initialisation à la place). , il renvoie la fonction d'initialisation en tant que fonction A de Lua afin que nous puissions l'appeler directement dans Lua.

Si une erreur se produit lors du chargement d'une bibliothèque dynamique ou de la recherche d'une fonction d'initialisation, loadlib renverra nil et un message d'erreur. Nous pouvons modifier le morceau de code précédent pour détecter les erreurs, puis appeler la fonction d'initialisation :

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

Généralement, nous nous attendons à ce que la bibliothèque de version binaire contienne un fichier stub similaire à l'extrait de code précédent. Vous pouvez installer le binaire. library avec désinvolture Placez-le dans un certain répertoire et modifiez simplement le chemin réel de la bibliothèque binaire correspondant au fichier stub.

Ajoutez le répertoire où se trouve le fichier stub à LUA_PATH Après l'avoir défini, vous pouvez utiliser la fonction require pour charger la bibliothèque C.