lua_pushthread聞きなれない型もありますが、大抵はnil、ブーリアン、数字、文字列、テーブル、関数です。nilはC言語で言うNULLと同じような感覚で「何も無い物」を表します。ブーリアンと数字と文字列はまぁそのままです。テーブルはLua最大の魅力の一つで、Luaが規定する型であれば何でも格納できるコレクション配列です。関数はC言語の関数ポインタで、これを通してLua側からC言語の関数を呼べたりします。軽量ユーザーデータはvoid*型で、これがLuaでのオブジェクト指向に一役買います。ユーザデータはメモリブロックになります。スレッドについては使う機会が出た時に説明します。スタック番号);第1引数にはスタックを持っているLuaステートを渡します。Luaステートはスタックを1つ持っています。第2引数のスタック番号は、型を知りたいスタックのインデックス(番号)を直接指定します。この指定の仕方こそがLuaのスタックを理解するとっても大切なポイントになります。スタックは値が入った箱がどんどん積み上げられていくイメージです。この時、「箱の一番下から」と「一番上から」という2つの指定方法が考えられます。Luaはこのどちらからの指定もできるようになっています。...」と正の値で番号が振られています。...」と下向きに負の値で位置が示されています。上の図で言えば-1も+5も同じ「IKD」という文字列が入ったスタックを示す事になります。同じスタックに対して2つの示し方があるのは、上から辿る事が便利なときも下から登る時が便利な時もあるためです。最初は「プラスとマイナスとどっちがどっちだっけ?」と迷うのですが、「下向きが負」もしくは「上向きが正」とどちらかの方向だけ覚えておけばすぐにイメージが固まると思います。LUA_TTHREAD:printf("THREAD\n");break;}}printf("-----------------------------\n\n");}現在のスタック数を取得する直接的な関数はありませんが、lua_gettop関数がスタックの一番上のプラス番号を返してくれるので、これがそのままスタック数になります。Luaのスタック番号は1基底なので、列挙も1番から始まります。lua_typeで指定の番号のスタックの型(type)を取得し、対応する表示を行っています。型が数字だった場合はlua_tonumber関数でそのスタックに格納されている数字を取得して表示しています。同様に文字列だった場合はlua_tostring関数で文字列を取得しています。ブーリアンはint型として値を返してきますのでそれを"true"か"false"に変換しています。他の型は型名だけです。"Marupeke");printStack(L);lua_close(L);}これを実行すると次のようにスタックの中身が表示されます:これであらゆるスタック操作を視覚的に見る事ができるようになりました。私の経験上ですが、スタックが視認できるようになるだけでLuaは相当にわかりやすくなります(^-^)Win32アプリケーションの場合はprintf関数が使えませんので、替わりにOutputDebugStringA関数を使うのが近道です。Luaにあるグローバル値をC言語にスクリプトとしての基本機能が「値の初期化」です。Luaにある数値をC言語に持ってくる方法は色々とありますが、一番簡単な方法はスクリプト内で「グローバル」として定義された値をC言語側で取得する方法です。"Marupeke";非常に簡単です。変数名に値を入れる、これだけ。LuaのスクリプトにはC言語のような「型定義」がありません。変数名を書いて値を代入できるんです。代入がなければ、その変数には「nil」が入っていると認識されます。num);}Luaファイルを読み込んで中身を解析するのがluaL_dofile関数です。第1引数には値を保持する管理人となるLuaステートを渡します。第2引数にLuaファイル名を渡します。拡張子が.luaとなっていますが、Luaファイルであれば名前は別に何でもかまいません。拡張子が無くてももちろんOKです。関数が成功すると0、失敗すると0以外の値が返ってきますので、エラー処理を行います。luaL_dofile関数が失敗するのは「ファイルがない」「Luaコードに間違いがある」場合です。この場合、スタックにエラー文字列が積まれます。それを文字列として表示すれば、具体的に何が起こったかを知る事ができます。Luaは突然終了する事が多いので、このエラー表示は大切です。読み込みと解析に成功したら、渡したLuaステートの中に「グローバル変数として」値が登録されます。これにアクセスするにはlua_getglobal関数を使います。第2引数に変数名を渡すとスタックにそれに該当するグローバル変数が積まれます。変数名は大文字小文字の区別があります。Luaはどのような値でもを一端スタックに積みます。lua_getglobal関数を呼ぶとスタックに値が乗せらます。指定の変数名がなければnilが乗ります。先ほど作ったprintStack関数を呼べば、スタックに値が積まれたかを確認できます:例えばゲームの初期値などはこの方法で設定する事が可能です。Luaからパラメータを読む方法は他にも色々ありますが、この章は事始めという事でここまでにしておきます。後章でより詳しく見ていくことにします。Luaの関数をC言語から呼ぶLuaはスクリプト上で独自の関数を作ることができます。val2;endLuaはfunction〜endで関数を定義するスタイルをとっています。これはVBなどと同じ方式です。C言語に慣れている人は上の関数定義に違和感を覚えてしまいます。val2;}見比べると、まず戻り値の型がLua内関数にはありません。引数の変数の型もありません。Luaは「型宣言無し言語」でして、代入された値によってその型をコロコロと変えることができるんです。そのため、戻り値や引数の型宣言が必要ないんです。「じゃ、じゃぁ、引数がval1=文字列、val2=数字も受け付けるの?」と疑問に思うわけですが、これ、ちゃんと受付けます。受け付けるのですが、実際に引き渡すと足し算の所でエラーになります。数字という演算が認められていないためです。Luaはインタプリタ型言語なので、構文が正しくてもプログラムが正しく動くかどうかはそこを通ってみないとわかりません。Lua関数には「複数の値を戻り値にできる」というC言語の関数を越える驚愕的な機能があります。val2;end戻り値をコンマで区切ると、いっぺんに複数の値を返せるんです。ここにC言語との親和性をゆるがす問題が出てきます。C言語の関数は複数の引数を取れますが、複数の戻り値を受け取れません。Luaで定義された関数を「C言語のスタイル」では呼べないんです。この違いを吸収するのがスタックです。Luaの関数から戻される値をスタックに積んでもらえばいいんです。C言語側ではそのスタックから値を貰うようにすれば、相互のやり取りが成立します。Luaの関数をC言語から呼ぶには、lua_getglobal関数で関数名を指定します。この段階でスタックにその関数を表す値が積まれます。次にLua側に渡す引数の値をC言語側で第1引数から積んでいきます。後はlua_pcall関数で関数名を指定してあげればLua側の関数が実行されます。関数が実行される時、スタックに積んだ物はlua_pcall関数を呼んだ時にスタックから取り出され、替わりに戻り値がスタック積まれます。num);lua_close(L);}Luaファイル側のcalc関数は先に説明した通りで、引数を2つ取り、戻り値が4つあります。C言語側がメインです。関数が定義されているLuaファイルを読み込んで解析し、Luaステート内にcalc関数の情報を登録します。これはluaL_dofile関数が担ってくれます。登録に成功したら、C言語側でLuaの関数をlua_getglobal関数で直接指定します。これで指定された関数がスタックに積まれます。関数もLuaにとっては値なんです。次に関数に渡す引数を積んでいきます。これは第1引数から順番に積みます。ここまでのスタック具合を表示してみるとこんな感じです:ちゃんと「関数、引数1、引数2」の順番に下から積まれていますよね。エラーハンドラ関数のスタックID);第1引数は関数が登録されているLuaステートです。第2引数は先に指定した関数の引数の数を渡します。第3引数は関数から戻される戻り値の数を指定します。第4引数は独自のエラーメッセージを取り扱う時に使いますが、デフォルトで良い場合は0を渡します。この関数が成功するとスタックに積まれていた「関数、引数1、引数2」はスタックから取り除かれます。正しくはlua_pcallで指定した引数の数+1だけ無くなります。関数から戻ってきた時には、lua_pcallで指定した戻り値の数分だけスタックに戻り値が積まれます。後は、スタックの値をC言語側で取り出すだけです。上のサンプルを実行すると次のような結果が得られます:加減乗除の結果がきちっとスタックに積まれているのがわかりますね。Lua側で定義した関数をC言語側で呼べると言う事は、C言語の仕事の一部をLua側に委託できるという事です。スクリプトっぽくなってきました。LuaとC言語の連携を見てきました。次章はLuaのもう一つの素晴らしい機能「コルーチン」のお話をします。