前節のl_add関数のスタック上の値について考えて見ましょう.
l_add関数を呼び出した後のLuaスタックには引数x,yや戻り値resultが残ったままになっているでしょうか.
もし残ったままならポップしなければいけないのかという疑問が残っています.
ここで次のようなコードを作ってみます.
前節でも登場したdumpStack関数を使用しています.
#include <stdio.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
void dumpStack(lua_State* L)
{
int i;
//スタックに積まれている数を取得する
int stackSize = lua_gettop(L);
for( i = stackSize; i >= 1; i-- ) {
int type = lua_type(L, i);
printf("Stack[%2d-%10s] : ", i, lua_typename(L,type) );
switch( type ) {
case LUA_TNUMBER:
//number型
printf("%f", lua_tonumber(L, i) );
break;
case LUA_TBOOLEAN:
//boolean型
if( lua_toboolean(L, i) ) {
printf("true");
}else{
printf("false");
}
break;
case LUA_TSTRING:
//string型
printf("%s", lua_tostring(L, i) );
break;
case LUA_TNIL:
//nil
break;
default:
//その他の型
printf("%s", lua_typename(L, type));
break;
}
printf("\n");
}
printf("\n");
}
int l_add(lua_State* L)
{
//第1引数 intとして取得
int x = luaL_checkint(L, -2);
//第2引数
int y = luaL_checkint(L, -1);
int result = x + y;
printf("%d + %d を計算します\n", x, y);
//戻り値をスタックに積む
lua_pushnumber(L, result);
//ダンプ2箇所目
printf("2番目\n");
dumpStack(L);
return 1; //戻り値の数を指定
}
int main (void)
{
int x = 10, y = 5;
//Luaを開く
lua_State* L = luaL_newstate();
//Luaの標準関数を使用できる状態にする
luaL_openlibs(L);
//l_add関数をadd関数としてLuaに登録
lua_register(L, "add", l_add);
//適当な値をプッシュ
lua_pushnumber(L, 444);
lua_pushnumber(L, 555);
//ダンプ1箇所目
printf("1番目\n");
dumpStack(L);
//Luaファイルsample.luaを読み込む
if( luaL_loadfile(L, "sample.lua") || lua_pcall(L, 0, 0, 0) ) {
printf("sample.luaを開けませんでした\n");
printf("error : %s\n", lua_tostring(L, -1) );
return 1;
}
//ダンプ1箇所目
printf("3番目\n");
dumpStack(L);
lua_close(L);
return 0;
}
3箇所からdumpStack関数を呼び出しています.
さて,実行結果は以下の通りとなりました.
実行結果
1番目
Stack[ 2- number] : 555.000000
Stack[ 1- number] : 444.000000
5 + 10 を計算します
2番目
Stack[ 3- number] : 15.000000
Stack[ 2- number] : 10.000000
Stack[ 1- number] : 5.000000
x + y は 15 です
3番目
Stack[ 2- number] : 555.000000
Stack[ 1- number] : 444.000000
実はLuaスタックは関数ごとに用意されています.
つまり,l_add関数からはmain関数側のスタックは見えないわけです.
また,l_add関数のスタックはLuaが勝手に削除してくれます.
よって,l_add関数上のスタックはわざわざポップする必要はありません.