6.3 モジュール
モジュールライブラリは Lua でモジュールを読み込むための基礎的な機能を提供します。このライブラリは require
という関数をグローバル環境に直接公開し、その他の値を全て package
というテーブルに公開します。
require (modname)
指定されたモジュールを読み込みます。この関数はまず package.loaded
テーブルを見て modname
が読み込まれているかどうかを確認します。もし読み込まれていれば、require
は package.loaded[modname]
にある値を返します (読み込みが行われなかったことは二番目の返り値が存在しないことから分かります)。そうでなければ、モジュールのローダーの検索が行われます。
ローダーの検索では package.searchers
というテーブルが使われます。このテーブルの要素は与えられたモジュールを何らかの方法で検索する関数であり、このテーブルを変更することで require
によるモジュール検索の方法を変更できます。デフォルトの package.searchers
を使った場合の検索処理を次に示します。
まず require
は package.preload[modname]
を調べます。この値が見つかれば、それがローダーとなります (この値は存在するなら必ず関数です)。見つからなければ package.path
にある Lua ローダーが検索されます。そこでも見つからなければ、package.cpath
にある C ローダーが検索されます。なお見つからなければ、オールインワンローダーが試されます (参照: package.searchers
)。
ローダーが見つかると、require
は二つの引数と共にそれを呼びます。一つ目の引数は modname
で、もう一つの省略可能な引数はローダーデータです。ローダーデータはローダーを検索する関数がローダーとは別に返す値であり、モジュールが使う値であれば何でも構いません。デフォルトの検索関数はローダーを見つけたインデックスをローダーデータとします (他にも、ファイルから読み込まれたときはファイルパスをローダーデータにするといった使い方が考えられます)。ローダーが nil でない値を返した場合にはその値が package.loaded[modname]
に代入され、nil を返した場合には true が package.loaded[modname]
に代入されます。いずれの場合でも、require
は最終的な package.loaded[modname]
の値を返します。それに加えて検索関数が返したローダーデータが二つ目の返り値となり、require
がモジュールをどのように見つけたかがここから分かります。
モジュールの読み込みと実行でエラーが発生した場合、およびモジュールのローダが見つからなかった場合には、require
はエラーを送出します。
package.config
パッケージライブラリのコンパイル時に定義される設定を表す文字列です。この文字列の意味は次の通りです:
- 最初の行はディレクトリを区切る文字列です。デフォルトは Window では
"\"
で、他の全てのシステムでは"/"
です。 - 二行目はパスのテンプレートを区切る文字列であり、デフォルトは
";"
です。 - 三行目はテンプレートで置換を表す文字列であり、デフォルトは
"?"
です。 - 四行目は Windows のパスにおいて実行形式のディレクトリで置き換わる文字列です。デフォルトは
"!"
です。 - 五行目は
luaopen_*
関数の名前を構築するときに使われる文字列であり、この文字列より後ろの部分は無視されます。デフォルトは"-"
です。
package.cpath
require
が C ローダーを検索するときに使うパスを表す文字列です。
Lua は C 用のパス package.cpath
を Lua 用のパス package.path
と同じ方法で初期化します。そのときには環境変数 LUA_CPATH_5_4
または LUA_CPATH
が定義されていればその値が、定義されていなければ luaconf.h
にあるデフォルトパスが使われます。
package.loaded
読み込まれたモジュールの管理に require
が利用するテーブルです。modname
を require したときに package.loaded[modname]
が nil でないなら、require
はその値を返して処理を終えます。
この変数は実際のテーブルへの参照でしかありません: この変数へ値を代入しても、require
が使うテーブルは変化しません。
package.loadlib (libname, funcname)
C ライブラリ libname
をホストプログラムに動的リンクします。
funcname
が "*"
の場合にはライブラリのリンクだけを行い、ライブラリに含まれるシンボルを他の動的リンクされるライブラリから利用可能にします。そうでなければ、loadlib
はライブラリに含まれる funcname
関数を探し、それを C 関数として返します。このためライブラリの funcname
関数は lua_CFunction
のプロトタイプを持つ必要があります。
これは低レベルの関数であり、パッケージとモジュールのシステムを完全に無視します。require
とは異なりパスの探索は行われず、拡張子を自動的に付与することもありません。libname
は C ライブラリの完全なファイル名でなければならず、場合によってはパスと拡張子が必要です。また funcname
は C ライブラリによってエクスポートされるのと全く同じ名前でなければなりません (この名前は使用される C コンパイラとリンカによって変化する可能性があります)。
この関数は標準 C でサポートされていないので、一部のプラットフォームでしか利用できません。具体的には、loadlib
が利用できるのは Windows, Linux, Mac OS X, Solaris, BSD, および標準 dlfcn
をサポートする Unix システムだけです。
package.path
require
が Lua ローダーを検索するときに使うパスを表す文字列です。
Lua はスタートアップ時にこの変数を初期化します。初期値は環境変数 LUA_PATH_5_4
または LUA_PAH
が定義されていればその値であり、定義されていなければ luaconf.h
にあるデフォルトのパスです。環境変数の値に含まれる ";;"
はデフォルトのパスで置換されます。
package.preload
モジュールごとのローダーを保存するテーブルです (参照: require
)。
この変数は実際のテーブルへの参照でしかありません。この変数へ値を代入しても、require
が使うテーブルは変化しません。
package.searchers
モジュールの検索方法を管理するために require
関数が使うテーブルです。
このテーブルの各要素は検索関数です。モジュールを探すとき、require
は検索関数を昇順に、モジュールの名前 (require
への引数) を唯一の引数として呼んでいきます。検索関数はモジュールを見つけると、モジュールのローダーと呼ばれる別の関数とローダーデータと呼ばれる追加の値を返します。ローダーデータはローダーに渡され、その後 require
の二つ目の返り値として返されます。モジュールを見つけられなかった検索関数はその理由を説明する文字列を返します (特に理由がないなら nil です)。
Lua はこのテーブルを四つの検索関数で初期化します。
一つ目の検索関数は package.preload
テーブルからローダーを検索します。
二つ目の検索関数は package.path
にあるパスを使って Lua ライブラリとしてローダーを検索します。この関数による検索は package.searchpath
で説明されるように行われます。
三つ目の検索関数は変数 package.cpath
にあるパスを使って C ライブラリとしてローダーを検索します。この関数による検索も package.searchpath
で説明されるのと同様です。例えば、もし package.cpath
に定義される C 用のパスが文字列
"./?.so;./?.dll;/usr/local/?/init.so"
なら、モジュール foo
の検索では ./foo.so
, ./foo.dll
, /usr/local/foo/init.so
がこの順番で検索されます。C ライブラリが見つかると検索関数はまず動的リンク機能を使ってそれをアプリケーションにリンクし、その後ローダーとして使われる C 関数をライブラリから関数を検索します。このとき検索される C 関数の名前はモジュールの名前に含まれるドットをアンダースコアに置き換えた文字列を "luaopen_"
の後ろに付けた文字列です。またモジュールの名前にハイフンが含まれると、最初のハイフンより後の (ハイフンを含む) 部分は削除されます。例えばモジュールの名前が a.b.c-v2.1
なら、検索される関数の名前は luaopen_a_b_c
となります。
四つ目の検索関数はオールインワンローダーを試します。このローダーは与えられたモジュールのルート名 (最初のドットまでの文字列) と同じ名前のライブラリを C パスから検索します。例えば a.b.c
を require
するときには、オールインワンローダーはまず a
という C ライブラリを検索します。これが見つかれば、その中にサブモジュールとして含まれる関数を検索します。今の例であれば luaopen_a_b_c
が検索されます。この機能を使ってパッケージを作ると、それぞれが独自のオープン関数を持った複数の C サブモジュールを単一のライブラリに入れられるようになります。
一つ目 (preload
を使うもの) を除いた全ての検索関数はモジュールを発見したファイルパスを二つ目の返り値として返します。これは package.searchpath
が返すのと同じ値です。一つ目の検索関数は常に文字列 ":preload:"
を返します。
検索関数はエラーを送出してはならず、また Lua に副作用を及ぼしてはいけません (アプリケーションにライブラリにリンクするといった C における副作用は許されます)。
package.searchpath (name, path [, sep [, rep]])
指定された path
から指定された name
を検索します。
path
はセミコロンで区切られたテンプレートの列です。テンプレートに含まれるクエスチョンマークは name
で置換され、sep
(デフォルトではドット) は rep
(システムのディレクトリ分離文字) で置換されます。この置換結果のファイルのオープンが試みられます。
例えば path
が次の文字列だったとします:
"./?.lua;./?.lc;/usr/local/?/init.lua"
このとき foo.a
に対して searchpath
を行うと ./foo/a.lua
, ./foo/a.lc
, /usr/local/foo/a/init.lua
がこの順番で検索されます。
読み込みモードでオープンできた最初のファイルの置換後の名前が返ります。どのファイルもオープンできなければ、fail とエラーメッセージが返ります (エラーメッセージには開こうとしたファイル名の一覧が表示されます)。