Lua関数
- グローバル変数
- 関数の環境
- 上位値(クロージャー内に保持される非ローカル変数)
C関数
- レジストリ
- 環境 ※Lua 5.2より廃止
- 上位値(クロージャー内に保持される非ローカル変数)
後者のC関数における格納場所に関する覚書。
レジストリ
Cコードからのみアクセス可能なグローバルテーブル。
複数のモジュール間で共有するデータを格納する際に利用する。
モジュール間でグローバルテーブル内の変数を参照する場合には、キー値を共有する必要がある。このキー値はモジュール間で共有するため、他の変数用のキーと重複しないように一意な値を指定する必要がある。
以下はサンプルコード(Luaスクリプトは全く使っていない。Cのコードのみ)。
#pragma once #include "lua.hpp" #ifdef LUADLL #define DllExport __declspec( dllexport ) #else #define DllExport __declspec( dllimport ) #endif namespace LuaModule { class DllExport MathContext { public: static const char* PI; MathContext(lua_State* L); virtual ~MathContext(); private: MathContext(); }; }
LuaModule.dll/MathContext.cpp
#include "MathContext.h" namespace LuaModule { const char* MathContext::PI = "LuaModule.MathContext.PI"; MathContext::MathContext(lua_State* L) { lua_pushlightuserdata(L, (void *)&PI); lua_pushstring(L, "3.141592"); lua_settable(L, LUA_REGISTRYINDEX); } MathContext::~MathContext() { } MathContext::MathContext() { } }
LuaSample.exe/LuaSample.cpp
#include <iostream> #include <process.h> #include "lua.hpp" #include "..\LuaModule\MathContext.h" int main(int argc, char** argv) { lua_State* L = luaL_newstate(); luaL_openlibs(L); LuaModule::MathContext context(L); lua_pushlightuserdata(L, (void*)&context.PI); lua_gettable(L, LUA_REGISTRYINDEX); const char* pi = lua_tostring(L, -1); printf("PI is %s\n", pi); lua_close(L); system("pause"); return 0; }
DLL側でグローバルテーブル内にPIの値を格納し、EXE側でPIの値を参照し、表示している。
静的な変数のアドレスはCのリンカにより一意性を保証されているため、これをキー値として利用。
環境
単一のモジュール内で共有するデータを格納する際に利用。
⇒
Lua 5.2より、C の関数が環境を持たなくなったため、
疑似インデックス LUA_ENVIRONINDEXは廃止されている。
Lua 5.2より、C の関数が環境を持たなくなったため、
疑似インデックス LUA_ENVIRONINDEXは廃止されている。
上位値
特定の関数内でのみ可視なCの静的変数に相当する。
LuaでC関数を新しく作成するたびに、その関数を任意の個数の上位値に関連づける事ができる。
上位値へのアクセスは疑似インデックスを使用する。
#include <iostream> #include <process.h> #include "lua.hpp" void createNewCounter(lua_State* L, int preset); static int counter(lua_State* L); int main(int argc, char** argv) { const char* fileName = "C:\\Develop\\LuaScript\\Sample.lua"; lua_State* L = luaL_newstate(); luaL_openlibs(L); createNewCounter(L, 10); if (luaL_dofile(L, fileName)) { printf("%s", lua_tostring(L, -1)); } createNewCounter(L, 100); if (luaL_dofile(L, fileName)) { printf("%s", lua_tostring(L, -1)); } lua_close(L); system("pause"); return 0; } void createNewCounter(lua_State* L, int preset) { //. カウンターの初期値をスタックにPush(上位値として使用する)。 lua_pushinteger(L, preset); //. クロージャーをスタックにPush。 //. 第3引数は上位値の数。今回は上位値は1つのみ。 lua_pushcclosure(L, &counter, 1); //. Pushしたクロージャーをグローバルテーブルに格納。 lua_setglobal(L, "counter"); } static int counter(lua_State* L) { //. 予めPushされている上位値を取得。 //. 上位値の取得はlua_upvalueindexを使用する。 int val = lua_tointeger(L, lua_upvalueindex(1)); //. 取得した値をインクリメントしてスタックへPush。 //. この値を関数の呼び出し元(Luaのスクリプト)で使用する。 lua_pushinteger(L, ++val); //. Pushされたインクリメント値を複製して再Push。 lua_pushvalue(L, -1); //. 再Pushした値を上位値へ移動。 //. 次回の関数呼び出しにおける上位値として使用される。 lua_replace(L, lua_upvalueindex(1)); return 1; }
"Sample.lua"
print(counter()) print(counter())
0 件のコメント:
コメントを投稿