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

Lua モジュールとパッケージ

モジュールはLuaから見ると、封入されたライブラリに似ています。 5.1 最初、Luaは標準のモジュール管理メカニズムを追加し、共有のコードをファイルにまとめることができ、APIインターフェースとして他の場所から呼び出すことができます。これにより、コードの再利用とコードの依存関係の低減が有利になります。

Luaのモジュールは変数、関数などの既知の要素で構成されるテーブルであり、そのため、テーブルを作成し、必要に応じて導出する定数や関数をその中に含め、最後にそのテーブルを返すことで簡単にモジュールを作成できます。以下は、カスタムモジュール module.lua を作成するためのファイルのフォーマットです:

-- ファイル名は 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

上記から分かるように、モジュールの構造はテーブルの構造であり、そのため、テーブル内の要素を操作するようにモジュール内の定数や関数を操作することができます。

上記のfunc2 プログラムブロック内で宣言されたローカル変数は、プライベートな関数を表しており、外部からこのプライベートな関数にアクセスすることはできません。このプライベートな関数を呼び出すには、モジュール内のパブリックな関数を通じて行わなければなりません。

require 関数

Luaはrequireという名前の関数を提供しており、モジュールをロードするために使用されます。モジュールをロードするには、単に呼び出すだけで十分です。例えば:

require("<モジュール名>")

または

require "<モジュール名>"

requireの実行後、モジュールの定数や関数からなるテーブルが返され、そのテーブルを含むグローバル変数も定義されます。

test_module.lua ファイル

-- test_module.lua ファイル
-- module モジュールは上記に記載の module.lua
require("module")
 
print(module.constant)
 
module.func3()

上記のコードの実行結果は以下の通りです:

これは定数です
これはプライベート関数です!

または、ロードされたモジュールに別名変数を定義して、呼び出しを簡単にします:

test_module2.lua ファイル

-- test_module2.lua ファイル
-- module モジュールは上記に記載の module.lua
-- 別名変数 m
local m = require("module")
 
print(m.constant)
 
m.func3()

上記のコードの実行結果は以下の通りです:

これは定数です
これはプライベート関数です!

ロードメカニズム

カスタムモジュールの場合、モジュールファイルはどのファイルディレクトリに置いてもかまいません。require 処理には独自のファイルパスのロード戦略があり、Lua ファイルや C プログラムライブラリからモジュールをロードしようとします。

require が Lua ファイルのパスを検索する際に使用するのは、グローバル変数 package.path に保存されています。Lua が起動すると、環境変数 LUA_PATH の値でこの環境変数を初期化します。この環境変数が見つからない場合、コンパイル時に定義されたデフォルトパスを使用して初期化します。

もちろん、LUA_PATH という環境変数がなくても、カスタム設定も行えます。現在のユーザーのルートディレクトリで .profile ファイルを開きます(存在しない場合は作成して開きます、または .bashrc ファイルを開いても構いません)。例えば、「~/lua/" このパスを LUA_PATH 環境変数に追加します:

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

ファイルパスは「;」で区切られており、最後の 2 新しいパスの後ろに元のデフォルトパスを追加するために「;;」を使用します。

次に、環境変数のパラメータを更新して即座に有効にします。

source ~/.profile

この時、package.pathの値は以下の通りです:

/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

その場合、require("module") を呼び出すと、以下のファイルディレクトリを開いてターゲットを検索しようとします。

/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

ターゲットファイルが見つかった場合、package.loadfile を呼び出してモジュールをロードします。そうでない場合、Cプログラムライブラリを探します。

検索するファイルパスはグローバル変数 package.cpath から取得され、この変数は環境変数 LUA_CPATH で初期化されます。

検索の戦略は上記と同じですが、現在検索しているのは so または dll タイプのファイルです。見つかった場合、require は package.loadlib を通じてそれをロードします。

C パッケージ

Lua と C は簡単に組み合わせることができます。C で Lua パッケージを書きます。

Lua でパッケージを書くのとは異なり、C パッケージは使用する前にまずロードおよび接続する必要があります。多くのシステムでは、動的結合ライブラリメカニズムを通じて最も簡単に実現できます。

Lua は loadlib という関数の内部ですべての動的結合機能を提供しています。この関数は 2 つの引数を持ちます: ライブラリの絶対パスと初期化関数。したがって、典型的な呼び出し例は以下の通りです:

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

loadlib 関数は指定されたライブラリを Lua にロードし、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 ライブラリをロードすることができます。