[Lua]カリー化ハウス LuaをC言語からアクセスすることを考えてみます。
curryをC言語から呼ぶのは簡単です。
こんな感じですね。
lua_getglobal(L, "curry")
lua_pushinteger(L, 1)
lua_pcall(L, 1, 1, 0);
問題は、返り値です。
返り値はFUNCTION型です。
これは、C言語では受け取ることができません。
スタックに置いたまま放置…とすると、それはそれで面倒です。
さてどうするか…Luaの適当な変数の中に突っ込んでおきましょう。
その適当な変数を提供するのがLuaL_refです。
int func = luaL_ref(L,LUA_REGISTRYINDEX);
// 関数を呼びたいとき
lua_rawgeti(L,LUA_REGISTRYINDEX, func);
lua_pushinteger(L, 2)
lua_pcall(L, 1, 1, 0);
// ここで、スタックに3という結果が入っている
lua_pop(L, 1);
// funcが必要なくなったとき
luaL_unref(L,LUA_REGISTRYINDEX, func);
luaL_refを呼び出すと、スタックの一番上の値をテーブルに入れ、値を返します。
今回は、LUA_REGISTORYINDEXという特殊なテーブルに入れています。
Luaには、いくつか特殊なテーブルがあります。
良く使うのは、LUA_GLOBALSINDEXとLUA_REGISTORYINDEXでしょう。
LUA_GLOBALSINDEXがLuaのグローバルテーブルで、グローバル変数が入っています。
LUA_REGISTORYINDEXは、Luaスクリプトではアクセスできず、C言語からのみアクセスできるテーブルです。
今回の場合は、Lua側からアクセスできなくてもよいのでLUA_REGISTORYINDEXに入れています。
luaL_refとlua_settableなどの関数との違いは、キーを指定しなくていいというところですね。
空いているキーを探して入れてくれるという、ちょっと便利な関数です。
lua_rawgetiはlua_rawgetのint版で、lua_rawgetはlua_gettableとほぼ同じものです。
要するに、添え字に数値を指定してテーブルから値をとってくる関数で、
おそらく、lua_gettableを使うより若干速いはずです。
lua_gettableとlua_rawgetの違いは、メタテーブルを参照するかしないかの違いです。
メタテーブルを説明するのは面倒なのですが、
Luaで組まれた領域をアクセスするときはlua_gettableを使う、と覚えておけばよいと思います。
今回はLuaがアクセスできない領域なので、lua_rawgetiを使っています。
最後、必要なくなったら、luaL_unrefで解放します。
そのうち、LuaのGCが領域を解放してくれるはずです。