文書の出典
- 出典
- Lua 5.5.1 Documentation
- 上流バージョン
- Lua 5.5.1
- 文書状態
- 翻訳
4.1 – スタック
LuaはCとの間で値を受け渡すために仮想スタックを使います。このスタックの各要素はLuaの値(nil、数値、文字列など)を表します。APIの関数は、受け取ったLuaステート引数を通じてこのスタックへアクセスできます。
LuaがCを呼び出すたびに、呼び出された関数は、以前のスタックや、まだアクティブなC関数のスタックから独立した新しいスタックを受け取ります。このスタックは最初にC関数へのすべての引数を含みます。C関数はここへ一時的なLua値を保存でき、呼び出し元へ返す結果をプッシュする必要があります(lua_CFunctionを参照)。
利便性のため、APIのほとんどの問い合わせ操作は厳格なスタック規律に従いません。代わりに、インデックスを使ってスタック内の任意の要素を参照できます。正のインデックスはスタック底を1として始まる絶対的なスタック位置を表し、負のインデックスはスタック最上部からの相対的なオフセットを表します。より具体的には、スタックにn個の要素がある場合、インデックス1は最初の要素(最初にスタックへプッシュされた要素)、インデックスnは最後の要素を表します。インデックス-1も最後の要素(最上部の要素)を表し、インデックス*-n*は最初の要素を表します。
4.1.1 – スタックサイズ
Lua APIとやり取りするときは、一貫性を確保する責任があります。特に、スタックオーバーフローを制御する責任があります。API関数を呼び出すときは、結果を収容する十分な領域がスタックにあることを保証しなければなりません。
上の規則には例外が1つあります。固定された結果数なしでLua関数を呼び出すと(lua_callを参照)、Luaはすべての結果に十分な領域がスタックにあることを保証します。ただし、追加の領域は保証しません。そのため、このような呼び出しの後にスタックへ何かをプッシュする前には、lua_checkstackを使うべきです。
LuaがCを呼び出すたびに、スタックには少なくともLUA_MINSTACK個の追加要素を置く領域があることを保証します。つまり、最大LUA_MINSTACK個の値を安全にプッシュできます。LUA_MINSTACKは20と定義されているため、コードにスタックへ要素をプッシュするループがなければ、通常はスタック領域を気にする必要はありません。必要なときはいつでも、関数lua_checkstackを使い、新しい要素をプッシュする十分な領域がスタックにあることを保証できます。
4.1.2 – 有効なインデックスと許容されるインデックス
スタックインデックスを受け取るAPIのすべての関数は、有効なインデックスまたは許容されるインデックスでのみ動作します。
有効なインデックスは、変更可能なLua値を保存する位置を参照するインデックスです。1からスタック最上部までのスタックインデックス(1 ≤ abs(index) ≤ top)に加え、Cコードからアクセスできるもののスタック内にはない位置を表す疑似インデックスを含みます。疑似インデックスは、レジストリ(§4.3を参照)とC関数の上位値(§4.2を参照)へアクセスするために使われます。
特定の変更可能な位置を必要とせず、値だけを必要とする関数(問い合わせ関数など)は、許容されるインデックスで呼び出せます。許容されるインデックスには任意の有効なインデックスを使えますが、スタック用に割り当てられた領域内でスタック最上部より後にある任意の正のインデックス、つまりスタックサイズまでのインデックスも使えます。(0が許容されるインデックスになることはありません。)現在のC関数が実際に持つ上位値数より大きな上位値のインデックス(§4.2を参照)も許容されます(ただし無効です)。特に記載がない限り、APIの関数は許容されるインデックスで動作します。
許容されるインデックスは、スタックを問い合わせるときに最上部に対する余分な検査を避ける役割があります。たとえば、C関数は第3引数が存在するか、つまり3が有効なインデックスかを確認せずに、第3引数を問い合わせられます。
許容されるインデックスで呼び出せる関数では、有効でないインデックスは仮想的な型LUA_TNONEの値を含むものとして扱われます。この型はnil値のように動作します。
4.1.3 – 文字列へのポインター
APIのいくつかの関数は、C文字列へのポインター(const char*)を引数として持ちます。一部の引数には関連付けられた長さ(size_t)があります。特に記載がない限り、関連付けられた長さがある場合、文字列には埋め込まれたゼロを含められます。また、長さが0ならポインターをNULLにできます。関連付けられた長さがない場合、ポインターはゼロ終端文字列を指す必要があります。どの場合も、関数が返るまで文字列の内容を変更しないでください。
APIのいくつかの関数は、スタック内のLua文字列へのポインター(const char*)も返します。(lua_pushfstring、lua_pushlstring、lua_pushstring、lua_tolstringを参照してください。補助ライブラリのluaL_checklstring、luaL_checkstring、luaL_tolstringも参照してください。)
一般に、Luaのガベージコレクションはメモリを解放または移動し、Luaステートが扱う文字列へのポインターを無効にすることがあります。これらのポインターを安全に使用できるよう、APIは、スタックインデックス内の文字列へのポインターが、そのインデックスの文字列値をスタックから削除しない限り有効であることを保証します。(ただし、別のインデックスへ移動することはできます。)インデックスが疑似インデックス(上位値を参照)の場合、そのポインターは、対応する呼び出しがアクティブで、対応する上位値が変更されていない間は有効です。
デバッグインターフェースの一部の関数、すなわちlua_getlocal、lua_getupvalue、lua_setlocal、lua_setupvalueも文字列へのポインターを返します。これらの関数では、呼び出し元の関数がアクティブで、指定されたクロージャー(指定されている場合)がスタック内にある間、ポインターが有効であることが保証されます。
これらの保証を除き、ガベージコレクターは内部文字列への任意のポインターを自由に無効化できます。