この初版は Lua 5.0 向けに書かれました。以後のバージョンでも多くの部分が関連性がありますが、いくつか違いがあります。
第 4 版は Lua 5.3 を対象としており、Amazon などの書店で購入できます。
この本を購入することで、Lua プロジェクトをサポートできます。
![]() |
Lua でのプログラミングLua | ![]() |
第4 部 C API 第 27 章 C 関数の記述テクニック |
Lua での「配列」は、特定の方法で使用されるテーブルの名前です。配列は、テーブルの操作に使用する同じ関数 (lua_settable
と lua_gettable
) を使用して操作できます。ただし、経済性と簡潔性という Lua の一般的な考え方とは逆に、API には配列操作用の特別な関数が用意されています。これはパフォーマンス上の理由です。この操作は、アルゴリズムの内部ループ (ソートなど) で頻発するので、この操作が速くなることで、関数の全体のパフォーマンスが大幅に向上する場合があります。
API で提供される配列操作用の関数は次のとおりです。
void lua_rawgeti (lua_State *L, int index, int key); void lua_rawseti (lua_State *L, int index, int key);
lua_rawgeti
と lua_rawseti
の説明は少し混乱する可能性があります。これは 2 つのインデックスを使用するからです。index
はスタック内のテーブルの位置を表し、key
はテーブル内の要素の位置を表します。lua_rawgeti(L, t, key)
の呼び出しは、次のシーケンスと同等です。lua_pushnumber(L, key); lua_rawget(L, t);
t
が正数の場合です (そうでない場合は、スタックの新しい項目を補正する必要があります)。lua_rawseti(L, t, key)
の呼び出し (t
が正数の場合) は次のとおりです。lua_pushnumber(L, key); lua_insert(L, -2); /* put `key' below previous value */ lua_rawset(L, t);どちらの関数も、単純操作を使用することに注意してください。これらは高速で、配列として使用されるテーブルは、メタメソッドをほとんど使用しません。
これらの関数の使用例については、前の l_dir
関数のループ本体を以下のように書き換えることができます。
lua_pushnumber(L, i++); /* key */ lua_pushstring(L, entry->d_name); /* value */ lua_settable(L, -3);次のように。
lua_pushstring(L, entry->d_name); /* value */ lua_rawseti(L, -2, i++); /* set table at key `i' */
より完全な例として、次のコードではマップ関数が実装されています。与えられた関数を配列のすべての要素に適用し、各要素を呼び出しの結果に置き換えます。
int l_map (lua_State *L) { int i, n; /* 1st argument must be a table (t) */ luaL_checktype(L, 1, LUA_TTABLE); /* 2nd argument must be a function (f) */ luaL_checktype(L, 2, LUA_TFUNCTION); n = luaL_getn(L, 1); /* get size of table */ for (i=1; i<=n; i++) { lua_pushvalue(L, 2); /* push f */ lua_rawgeti(L, 1, i); /* push t[i] */ lua_call(L, 1, 1); /* call f(t[i]) */ lua_rawseti(L, 1, i); /* t[i] = result */ } return 0; /* no results */ }この例では 3 つの新しい関数が導入されています。
luaL_checktype
関数 (lauxlib.h
から) は、指定された引数が指定された型であることを確認します。そうでない場合は、エラーを発生させます。luaL_getn
関数は、指定されたインデックスの配列のサイズを取得します (table.getn
はそのジョブを実行するために luaL_getn
を呼び出します)。lua_call
関数は、保護されていない呼び出しを行います。lua_pcall
と似ていますが、エラーが発生した場合はエラーコードを返すのではなく、エラーをスローします。アプリケーションでメインコードを記述している場合は、エラーをキャッチしたいので、lua_call
は使用しないでください。ただし、関数を記述している場合は、通常 lua_call
を使用することが適切です。エラーが発生した場合は、誰かがそのエラーに対処できるようにそのままにしておきます。Copyright © 2003–2004 Roberto Ierusalimschy. All rights reserved. | ![]() |