この初版は Lua 5.0 向けに書かれています。後のバージョンでもほぼ通用しますが、いくつかの違いがあります。
第4版は Lua 5.3 を対象としており、Amazon や他の書店で入手可能です。
本書を購入することで、Lua プロジェクトの支援にもなります。


26.2 – C ライブラリ

Lua ライブラリは、複数の Lua 関数を定義し、それらを適切な場所(通常はテーブルのエントリ)に格納するチャンクです。Lua 用の C ライブラリはこの動作を模倣します。C 関数の定義に加えて、Lua ライブラリのメインチャンクに対応する特別な関数を定義する必要があります。この関数が呼び出されると、ライブラリのすべての C 関数を登録し、適切な場所に格納します。Lua のメインチャンクと同様に、ライブラリで初期化が必要なものはすべて初期化します。

Lua は、この登録プロセスを通じて C 関数を「認識」します。C 関数が Lua に表現され、格納されると、Lua プログラムは、そのアドレス(関数を登録するときに Lua に渡すアドレス)への直接参照を通じて、その関数を呼び出します。つまり、Lua は、関数が登録されると、関数名、パッケージの場所、または可視性ルールに依存せずに、関数を呼び出すことができます。通常、C ライブラリには、ライブラリを開く関数である、単一のパブリック (extern) 関数があります。他のすべての関数はプライベートであり、C では static として宣言できます。

C 関数で Lua を拡張する場合、1 つの C 関数のみを登録する場合でも、コードを C ライブラリとして設計することをお勧めします。遅かれ早かれ(通常は早かれ)他の関数が必要になります。いつものように、補助ライブラリはこの作業のためのヘルパー関数を提供します。luaL_openlib 関数は、C 関数とそのそれぞれの名前のリストを受け取り、それらすべてをライブラリ名を持つテーブル内に登録します。例として、以前に定義した l_dir 関数を含むライブラリを作成したいとします。まず、ライブラリ関数を定義する必要があります

    static int l_dir (lua_State *L) {
       ...  /* as before */
    }
次に、すべての関数とそのそれぞれの名前を含む配列を宣言します。この配列の要素の型は luaL_reg で、これは文字列と関数ポインタの 2 つのフィールドを持つ構造体です。
    static const struct luaL_reg mylib [] = {
      {"dir", l_dir},
      {NULL, NULL}  /* sentinel */
    };
この例では、宣言する関数は l_dir のみです。配列の最後のペアは、その終わりを示すために {NULL, NULL} である必要があることに注意してください。最後に、luaL_openlib を使用してメイン関数を宣言します
    int luaopen_mylib (lua_State *L) {
      luaL_openlib(L, "mylib", mylib, 0);
      return 1;
    }
luaL_openlib の 2 番目の引数はライブラリ名です。この関数は、指定された名前のテーブルを作成(または再利用)し、配列 mylib で指定された名前と関数のペアでテーブルを満たします。luaL_openlib 関数を使用すると、ライブラリのすべての関数に共通のアップバリューを登録することもできます。今のところ、アップバリューを使用していないため、呼び出しの最後の引数はゼロです。戻ると、luaL_openlib は、ライブラリを開いたテーブルをスタックに残します。luaopen_mylib 関数は 1 を返し、この値を Lua に返します。(Lua ライブラリと同様に、この戻り値はオプションです。ライブラリは既にグローバル変数に割り当てられているためです。繰り返しますが、Lua ライブラリと同様に、コストはかかりません。また、場合によっては役立つことがあります。)

ライブラリの完成後、インタープリターにリンクする必要があります。Lua インタープリターがこの機能をサポートしている場合、最も便利な方法は動的リンク機能を使用することです。(セクション 8.2 の動的リンクに関する説明を参照してください。)この場合、コードを使用して動的ライブラリ(Windows では .dll ファイル、Linux では .so ファイル)を作成する必要があります。その後、loadlib を使用して Lua 内からライブラリを直接ロードできます。呼び出し

    mylib = loadlib("fullname-of-your-library", "luaopen_mylib")
luaopen_mylib 関数を Lua 内の C 関数に変換し、この関数を mylib に割り当てます。(そのため、luaopen_mylib は他の C 関数と同じプロトタイプを持つ必要があります。)次に、mylib() の呼び出しで luaopen_mylib が実行され、ライブラリが開きます。

インタープリターが動的リンクをサポートしていない場合は、新しいライブラリを使用して Lua を再コンパイルする必要があります。その上、新しい状態を開くときにこのライブラリを開く必要があることをスタンドアロンインタープリターに指示する方法が必要です。いくつかのマクロがこのタスクを容易にします。まず、次の内容のヘッダーファイル(mylib.h と呼ぶことにします)を作成する必要があります

    int luaopen_mylib (lua_State *L);
    
    #define LUA_EXTRALIBS { "mylib", luaopen_mylib },
最初の行は open 関数を宣言します。次の行は、マクロ LUA_EXTRALIBS を、インタープリターが新しい状態を作成するときに呼び出す関数配列の新しいエントリとして定義します。(この配列の型は struct luaL_reg[] なので、そこに名前を付ける必要があります。)

このヘッダーファイルをインタープリターに含めるには、コンパイラオプションでマクロ LUA_USERCONFIG を定義します。コマンドラインコンパイラの場合、通常は次のようなオプションを追加する必要があります

    -DLUA_USERCONFIG=\"mylib.h\"
(バックスラッシュはシェルから引用符を保護します。これらの引用符は、インクルードファイル名を指定する場合に C で必要です。)統合開発環境では、プロジェクト設定で同様の内容を追加する必要があります。その後、lua.c を再コンパイルすると、mylib.h が含まれるため、開くライブラリのリストで LUA_EXTRALIBS の新しい定義が使用されます。