Luaに構造体はないがテーブルがあり構造体と同じような書き方ができる。
LuaとC++の通信はLuaのスタックを介して行われるため、Luaのスタックの挙動を知っておく必要がある。
1.lua_getglobalでスクリプト内のテーブルへの参照をスタックへPush
2.lua_getfieldでテーブルへの参照から指定したキーの値をスタックへPush
3.lua_tostringでスタックの先頭の値を読み込んで表示
4.スタックをPopして次の処理に備える
#include <lua.hpp> // lua54.dllが必要 #pragma comment(lib, "lua54.lib") // Luaスクリプト static const char* script = R"(
MyLuaTable ={ val_a = "VAL_A", val_b = "VAL_B", val_c = "VAL_C", val_d = "VAL_D", }
)"; int main() { lua_State* luas = luaL_newstate(); // Luaの標準ライブラリを読み込む luaL_openlibs(luas); // 文字列で与えてスクリプトを実行する luaL_dostring(luas, script); // テーブルへアクセス lua_getglobal(luas, "MyLuaTable");// MyLuaTableへの参照をスタックの一番上にPush{ // lua_getfieldでテーブルから値を取得 // 第一引数 ... lua_State // 第二引数 ... テーブルのスタック上の位置を現在のスタック位置からの差で表す // 第三引数 ... テーブルのキー /* * スタックの状態 * 4 □ * 3 □ * 2 □ 現在位置==2。 現在位置-1 == 1。従ってlua_getfieldは'1'で参照されているテーブルから'val_a'を取り出し、ここへPushする * 1 ■ MyLuaTableへの参照 lua_getglobalによりPushされている */ lua_getfield(luas, -1, "val_a"); // val_aの値(現在位置からMyLuaTableまでの距離は-1)をスタックの一番上にPush const char* value = lua_tostring(luas, -1); // スタックの一番上の値を取得 printf("value: %s\n", value); lua_pop(luas, 1/*要素を一つPOP*/); // スタックの一番上の要素をPop。これで現在のスタック位置が2に戻る }
{ lua_getfield(luas, -1, "val_b"); // val_bの値(MyLuaTableまでの距離は-1)をスタックの一番上にPush const char* value = lua_tostring(luas, -1); // スタックの一番上の値を取得 printf("value: %s\n", value); lua_pop(luas, 1/*要素を一つPOP*/); // スタックの一番上の要素をPop }
// Luaの終了。全てのメモリ解放 lua_close(luas); }
lua_getglobalとlua_getfieldの挙動がわからなかったので、スタックの状態を確認する。
以下のコードはスクリプトで定義されたテーブルへアクセスするために、各値をひたすらスタックへ積んでいく。
#include <lua.hpp> // lua54.dllが必要 #pragma comment(lib, "lua54.lib") // Luaスクリプト static const char* script = R"(
MyLuaTable_1 ={ val_1_a = "VAL_1_A", val_1_b = "VAL_1_B", val_1_c = "VAL_1_C", val_1_d = "VAL_1_D", } MyLuaTable_2 ={ val_2_a = "VAL_2_A", val_2_b = "VAL_2_B", val_2_c = "VAL_2_C", val_2_d = "VAL_2_D", }
)";
// Lua スタックの内容を表示 void print_stack(lua_State* luas) { // スタックのトップの位置を取得 int top = lua_gettop(luas); // 全てのスタックの内容を表示 // Luaのスタックは1から始まる for (int pos = 1; pos <= top; pos++) { int type = lua_type(luas, pos); printf("%d: ", pos); switch (type) { case LUA_TSTRING: printf("'%s'", lua_tostring(luas, pos)); break; case LUA_TBOOLEAN: printf(lua_toboolean(luas, pos) ? "true" : "false"); break; case LUA_TNUMBER: printf("%g", lua_tonumber(luas, pos)); break; case LUA_TNIL: printf("nil"); break; case LUA_TTABLE: printf("table Reference"); break; case LUA_TFUNCTION: printf("function"); break; case LUA_TUSERDATA: printf("userdata"); break; case LUA_TTHREAD: printf("thread"); break; case LUA_TLIGHTUSERDATA: printf("light userdata"); break; default: printf("unknown"); break; } printf("\n"); } }
int main() { lua_State* luas = luaL_newstate(); // Luaの標準ライブラリを読み込む luaL_openlibs(luas); // 文字列で与えてスクリプトを実行する luaL_dostring(luas, script); { // テーブルへアクセス lua_getglobal(luas, "MyLuaTable_1");// MyLuaTable_1への参照をスタックの一番上にPush lua_getglobal(luas, "MyLuaTable_2");// MyLuaTable_2への参照をスタックの一番上にPush lua_getfield(luas, -1, "val_2_a"); // val_2_aの値(MyLuaTable_2までの距離は-1)をスタックの一番上にPush lua_getfield(luas, -2, "val_2_b"); // val_2_bの値(MyLuaTable_2までの距離は-2)をスタックの一番上にPush lua_getfield(luas, -3, "val_2_c"); // val_2_aの値(MyLuaTable_2までの距離は-3)をスタックの一番上にPush lua_getfield(luas, -4, "val_2_d"); // val_2_bの値(MyLuaTable_2までの距離は-4)をスタックの一番上にPush // [現在位置-5] にはMyLuaTable_2への参照が積まれている lua_getfield(luas, -6, "val_1_a"); // val_1_aの値(MyLuaTable_1までの距離は-6)をスタックの一番上にPush lua_getfield(luas, -7, "val_1_b"); // val_1_bの値(MyLuaTable_1までの距離は-7)をスタックの一番上にPush lua_getfield(luas, -8, "val_1_c"); // val_1_cの値(MyLuaTable_1までの距離は-8)をスタックの一番上にPush lua_getfield(luas, -9, "val_1_d"); // val_1_dの値(MyLuaTable_1までの距離は-9)をスタックの一番上にPush } print_stack(luas); // スタックの内容を表示 // Luaの終了。全てのメモリ解放 lua_close(luas); }
lua_tostringの第二引数には、スタックの先頭からの距離を指定する。-1は先頭に積まれている値を指す。例えば-4を指定すれば、先頭から4つ目の値へアクセスする。
// テーブルへアクセス lua_getglobal(luas, "MyLuaTable_1");// MyLuaTable_1への参照をスタックの一番上にPush lua_getglobal(luas, "MyLuaTable_2");// MyLuaTable_2への参照をスタックの一番上にPush lua_getfield(luas, -1, "val_2_a"); // val_2_aの値(MyLuaTable_2までの距離は-1)をスタックの一番上にPush lua_getfield(luas, -2, "val_2_b"); // val_2_bの値(MyLuaTable_2までの距離は-2)をスタックの一番上にPush lua_getfield(luas, -3, "val_2_c"); // val_2_aの値(MyLuaTable_2までの距離は-3)をスタックの一番上にPush lua_getfield(luas, -4, "val_2_d"); // val_2_bの値(MyLuaTable_2までの距離は-4)をスタックの一番上にPush // [現在位置-5] にはMyLuaTable_2への参照が積まれている lua_getfield(luas, -6, "val_1_a"); // val_1_aの値(MyLuaTable_1までの距離は-6)をスタックの一番上にPush lua_getfield(luas, -7, "val_1_b"); // val_1_bの値(MyLuaTable_1までの距離は-7)をスタックの一番上にPush lua_getfield(luas, -8, "val_1_c"); // val_1_cの値(MyLuaTable_1までの距離は-8)をスタックの一番上にPush lua_getfield(luas, -9, "val_1_d"); // val_1_dの値(MyLuaTable_1までの距離は-9)をスタックの一番上にPush
///////////////////////////////////////// // 現在位置から -4 の位置にある値を取得 const char* value = lua_tostring(luas, -4); // val_1_a の値を取得 printf("value: %s\n", value);