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 件のコメント:
コメントを投稿