このページの内容

6.4 – モジュール

パッケージライブラリは、Luaでモジュールを読み込むための基本的な機能を提供します。1つの関数requireをグローバル環境へ直接エクスポートします。そのほかはすべてテーブルpackageへエクスポートされます。


require (modname)

指定されたモジュールを読み込みます。関数は最初にpackage.loadedテーブルを調べ、modnameがすでに読み込まれているかを判定します。読み込まれていれば、requirepackage.loaded[modname]に保存された値を返します。(この場合に第2結果がないことは、この呼び出しでモジュールを読み込む必要がなかったことを示します。)それ以外の場合、モジュールのローダーを探します。

ローダーを探すとき、requireはテーブルpackage.searchersに従います。このテーブルの各項目は、特定の方法でモジュールを検索する検索関数です。このテーブルを変更すると、requireがモジュールを探す方法を変更できます。以下の説明はpackage.searchersのデフォルト設定に基づきます。

最初にrequirepackage.preload[modname]を問い合わせます。値があれば、その値(関数でなければなりません)がローダーです。それ以外の場合、requirepackage.pathに保存されたパスを使ってLuaローダーを検索します。それにも失敗すると、package.cpathに保存されたパスを使ってCローダーを検索します。それにも失敗すると、オールインワンローダーを試します(package.searchersを参照)。

ローダーが見つかると、requireは2つの引数、modnameと、検索関数も返した追加値であるローダーデータを指定してローダーを呼び出します。ローダーデータにはモジュールに役立つ任意の値を使用できます。デフォルトの検索関数では、ローダーが見つかった場所を示します。(たとえば、ローダーがファイルから得られた場合、この追加値はファイルパスです。)ローダーがnilでない値を返すと、requireは返された値をpackage.loaded[modname]へ代入します。ローダーがnilでない値を返さず、package.loaded[modname]へ値を代入してもいなければ、requireはこの項目へtrueを代入します。どの場合も、requirepackage.loaded[modname]の最終値を返します。その値に加え、requireは第2結果として、検索関数が返したローダーデータも返します。これはrequireがモジュールを見つけた方法を示します。

モジュールの読み込みまたは実行中にエラーがある場合、あるいはモジュールのローダーを見つけられない場合、requireはエラーを発生させます。


package.config

パッケージのコンパイル時設定の一部を表す文字列です。この文字列は次の行の列です。

  • 第1行はディレクトリ区切り文字列です。デフォルトはWindowsでは’

    \

    ‘、そのほかのすべてのシステムでは’

    /

    ‘です。

  • 第2行はパス内のテンプレートを区切る文字です。デフォルトは’

    ;

    ‘です。

  • 第3行はテンプレート内の置換地点を示す文字列です。デフォルトは’

    ?

    ‘です。

  • 第4行は、Windowsのパス内で実行ファイルのディレクトリへ置き換えられる文字列です。デフォルトは’

    !

    ‘です。

  • 第5行は、

    luaopen_

    関数名を構築するとき、その後のすべてのテキストを無視するための記号です。デフォルトは’

    -

    ‘です。


package.cpath

requireがCローダーを検索するために使うパスを持つ文字列です。

Luaは、環境変数LUA_CPATH_5_5、環境変数LUA_CPATH、またはluaconf.hで定義されたデフォルトパスを使い、Luaパスpackage.pathと同じ方法でCパスpackage.cpathを初期化します。


package.loaded

どのモジュールがすでに読み込まれているかをrequireが管理するために使うテーブルです。モジュールmodnameをrequireするとき、package.loaded[modname]がfalseでなければ、requireはそこに保存された値をそのまま返します。

この変数は実際のテーブルへの参照にすぎません。この変数へ代入しても、requireが使うテーブルは変わりません。実際のテーブルはCレジストリ(§4.3を参照)に、文字列であるキーLUA_LOADED_TABLEでインデックスを付けて保存されています。


package.loadlib (libname, funcname)

ホストプログラムをCライブラリlibnameへ動的リンクします。

funcnameが”*”なら、ライブラリへリンクするだけで、そのライブラリがエクスポートするシンボルを、動的リンクされるほかのライブラリから利用できるようにします。それ以外の場合、ライブラリ内で関数funcnameを探し、その関数をC関数として返します。したがって、funcnamelua_CFunctionプロトタイプに従う必要があります(lua_CFunctionを参照)。

これは低水準の関数です。パッケージとモジュールのシステムを完全に迂回します。requireとは異なり、パス検索を行わず、拡張子も自動的に追加しません。libnameは、必要ならパスと拡張子を含むCライブラリの完全なファイル名でなければなりません。funcnameはCライブラリがエクスポートする正確な名前でなければなりません(使用するCコンパイラーとリンカーに依存する場合があります)。

この機能はISO Cでサポートされません。そのため、loadlibはLinux、Windows、Mac OS X、Solaris、BSD、およびdlfcn標準をサポートするそのほかのUnixシステムなど、一部のプラットフォームでのみ利用できます。

この関数は、Luaがシステム内の任意の読み取り可能な動的ライブラリの任意の関数を呼び出せるようにするため、本質的に安全ではありません。(Luaは、任意の関数が適切なプロトタイプを持ち、適切なプロトコルに従うと仮定して呼び出します(lua_CFunctionを参照)。したがって、任意の動的ライブラリ内の任意の関数を呼び出すと、多くの場合アクセス違反になります。)


package.path

requireがLuaローダーを検索するために使うパスを持つ文字列です。

起動時にLuaは、環境変数LUA_PATH_5_5の値、環境変数LUA_PATHの値、または、これらの環境変数が定義されていなければluaconf.hで定義されたデフォルトパスで、この変数を初期化します。環境変数の値にある”;;”はデフォルトパスへ置き換えられます。


package.preload

特定のモジュールのローダーを保存するテーブルです(requireを参照)。

この変数は実際のテーブルへの参照にすぎません。この変数へ代入しても、requireが使うテーブルは変わりません。実際のテーブルはCレジストリ(§4.3を参照)に、文字列であるキーLUA_PRELOAD_TABLEでインデックスを付けて保存されています。


package.searchers

モジュールを探す方法をrequireが管理するために使うテーブルです。

このテーブルの各項目は検索関数です。モジュールを探すとき、requireは、モジュール名(requireへ渡された引数)だけを引数として、これらの検索関数を昇順で呼び出します。検索関数がモジュールを見つけると、別の関数であるモジュールのローダーと、ローダーへ渡され、requireの第2結果として返される追加値であるローダーデータを返します。モジュールを見つけられなければ、理由を説明する文字列(何も伝えることがなければnil)を返します。

Luaはこのテーブルを4つの検索関数で初期化します。

第1検索関数は、package.preloadテーブル内でローダーを探すだけです。

第2検索関数は、package.pathに保存されたパスを使い、Luaライブラリとしてローダーを探します。検索は関数package.searchpathで説明されている方法で行われます。

第3検索関数は、変数package.cpathが指定するパスを使い、Cライブラリとしてローダーを探します。ここでも、検索は関数package.searchpathで説明されている方法で行われます。たとえば、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になります。

第4検索関数はオールインワンローダーを試します。指定されたモジュールのルート名を持つライブラリをCパスで検索します。たとえば、a.b.cをrequireするとき、aのCライブラリを検索します。見つかると、その中でサブモジュールのopen関数を探します。この例ではluaopen_a_b_cです。この機能により、各サブモジュールが元のopen関数を保ったまま、1つのパッケージへ複数のCサブモジュールをまとめられます。

第1検索関数(preload)を除くすべての検索関数は、package.searchpathが返した、モジュールが見つかったファイルパスを追加値として返します。第1検索関数は常に文字列”:preload:”を返します。

検索関数はエラーを発生させず、Luaで副作用を持つべきではありません。(たとえばアプリケーションをライブラリへリンクすることで、Cでは副作用を持つ場合があります。)


package.searchpath (name, path [, sep [, rep]])

指定されたpath内で、指定されたnameを検索します。

パスは、セミコロンで区切られた一連のテンプレートを含む文字列です。関数は各テンプレートについて、テンプレート内の各疑問符(存在する場合)を、name内のsep(デフォルトではドット)をすべてrep(デフォルトではシステムのディレクトリ区切り)へ置き換えたコピーで置換し、その結果のファイル名を開こうとします。

たとえば、パスが次の文字列なら

     "./?.lua;./?.lc;/usr/local/?/init.lua"

名前foo.aの検索は、ファイル./foo/a.lua./foo/a.lc/usr/local/foo/a/init.luaをこの順で開こうとします。

読み取りモードで開けた最初のファイルについて、ファイルを閉じた後、その結果の名前を返します。どれも成功しなければ、failとエラーメッセージを返します。(このエラーメッセージは、開こうとしたすべてのファイル名を列挙します。)