この第 1 版は Lua 5.0 向けに書かれました。依然として後々のバージョンにも大部分は関連がありますが、いくらか違いがあります。
第 4 版は Lua 5.3 を対象とし、Amazon や他の書店で購入できます。
この本を買うことで Lua プロジェクトの支援 にも協力できます。


25.2 – Lua 関数の呼び出し

Lua の大きな強みとしては、コンフィギュレーションファイルで関数を定義し、アプリケーションからその関数を呼び出すことができることです。たとえば、関数のグラフを描画するアプリケーションを書くことができ、Lua を使用して描画する関数を定義できます。

関数を呼び出す API プロトコルは単純です: まず、呼び出す関数をプッシュします。次に、呼び出しに対する引数をプッシュします。そして、lua_pcall を使用して実際の呼び出しを行います。最後に、結果をスタックからポップします。

例として、コンフィギュレーションファイルに次のよう関数があるとします。

    function f (x, y)
      return (x^2 * math.sin(y))/(1 - x)
    end
そして、与えられた xy について C で z = f(x, y) を評価したいとします。Lua ライブラリを既にオープンしてコンフィギュレーションファイルを実行していると仮定すると、次の C 関数でこの呼び出しをカプセル化できます。
    /* call a function `f' defined in Lua */
    double f (double x, double y) {
      double z;
    
      /* push functions and arguments */
      lua_getglobal(L, "f");  /* function to be called */
      lua_pushnumber(L, x);   /* push 1st argument */
      lua_pushnumber(L, y);   /* push 2nd argument */
    
      /* do the call (2 arguments, 1 result) */
      if (lua_pcall(L, 2, 1, 0) != 0)
        error(L, "error running function `f': %s",
                 lua_tostring(L, -1));
    
      /* retrieve result */
      if (!lua_isnumber(L, -1))
        error(L, "function `f' must return a number");
      z = lua_tonumber(L, -1);
      lua_pop(L, 1);  /* pop returned value */
      return z;
    }

lua_pcall には、渡す引数の数と必要な結果の数を指定して呼び出します。4 番目の引数はエラー処理関数を指定します。これは後で説明します。Lua の代入と同様に、lua_pcall は指定した結果の実際の数に調整し、必要に応じて nil をプッシュするか余分な値を破棄します。lua_pcall は結果をプッシュする前に、関数とその引数をスタックから削除します。関数が複数の結果を返す場合、最初の結果が最初にプッシュされます。つまり、結果が n 個ある場合、最初の結果はインデックス -n に、最後の結果はインデックス -1 にあります。

lua_pcallの実行中にエラーが発生すると、lua_pcallはゼロ以外の値を返します。さらに、エラーメッセージをスタックにプッシュします(ただし、関数とその引数はポップします)。ただし、lua_pcallはメッセージをプッシュする前に、エラーハンドラ関数がある場合はその関数を呼び出します。エラーハンドラ関数を指定するには、lua_pcallの最後の引数を使用します。ゼロはエラーハンドラ関数がないことを意味します。つまり、最終的なエラーメッセージは元のメッセージです。それ以外の場合、その引数はエラーハンドラ関数が配置されたスタック内のインデックスにする必要があります。そのような場合、ハンドラは呼び出される関数とその引数より前にスタックにプッシュされる必要があることに注意してください。

通常のエラーの場合、lua_pcallはエラーコードLUA_ERRRUNを返します。2つの特殊な種類のエラーは、エラーハンドラを実行しないため、それぞれ異なるコードが割り当てられます。最初の種類は、メモリ割り当てエラーです。このようなエラーの場合、lua_pcallは常にLUA_ERRMEMを返します。2番目の種類は、Luaがエラーハンドラ自体を実行している間に発生するエラーです。その場合、エラーハンドラを再度呼び出すことはあまり有用ではないため、lua_pcallはコードLUA_ERRERRで即座に返します。