この初版は 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. | ![]() |