__newindex
カスタム関数とand__index
関数の登録を2つの別々の関数に分離するためのコードをいくつか作成しました。私のコードの目標は、特異性のサブレベルに基づいて編成された関数と変数をLuaスクリプトライターに表示することです。たとえば、ユーザーは次のコマンドを使用できます。
orc.chief.attack();
orc.chief.flee();
orc.chief.hp = 100;
orc.pawn.attack();
elf.wood.attack();
elf.wood.hp = 200;
つまり、基本的には2層のシステムで、次に関数呼び出しまたは変数があります。私がLuaを正しく理解していれば、それはテーブル内のテーブル内のメタテーブルです。ユーザーが変数を設定するときは、呼び出しをトリップする必要があり__newindex
ます(値の設定を処理するだけでなく、モーターを介してアニメーション化する物理オブジェクトにアクセスするため)。また、テーブルのチーフテーブルには、それがであるかorc
どうかに関係なく、割り当てられた多くの関数が表示されていると思います。コードの開発中に新しい変数と関数を簡単に追加できるように、2つの関数を作成しました。1つは関数を作成するためのもので、もう1つは変数を作成するためのものです。関数は関数と変数を登録するだけですattack
__newindex
create
create
新しいテーブル要素を作成し、との関数を登録するだけ__newindex
です__index
。以下はコードです:
int orcChiefhp;
luaL_Reg Orc_Module[] = {
{"attack", OrcAttack},
{"flee", OrcFlee},
{NULL, NULL}};
const luaL_Reg orcChief_metareg[] = {
{"__index", orcChief__index},
{"__newindex", orcChief__newindex},
{NULL, NULL}};
int OrcAttack(lua_State *L)
{
//code to cause the motors to swing the weapon...
return 0;//0 parameters come back as the data
}
int orcChief__newindex(lua_State *L)
{
const char *idx;
if(lua_isstring(L,2))
{
idx = lua_tostring(L,2);//gets the string so we can get the variable of the struct
if(strcmp(idx, "hp")==0)
{
lua_pushnumber(L, orcChiefhp);
}
else
lua_pushnil(L);
}
return 1;
}
void registerFunctions(lua_State *L, const char *libname, const char *sublibname, const luaL_Reg *funcs)
{
int isitnil;
lua_getglobal(L, libname);
isitnil = lua_isnil(L, -1);
if(isitnil)
{
lua_pop(L, 1);
lua_newtable(L); // create 'libname' table
}
// no sublib: just import our library functions directly into lib and we're done
if (sublibname == NULL)
{
luaL_setfuncs(L, funcs, 0);
}
// sublib: create a table for it, import functions to it, add to parent lib
else
{
lua_newtable(L);
luaL_setfuncs(L, funcs, 0);
lua_setfield(L, -2, sublibname);
}
if(isitnil)
lua_setglobal(L, libname);//this will pop off the global table.
else
lua_pop(L, 1);//the global table is still on the stack, pop it off
}
void registerIntegerVariable(lua_State *L, const char *libname, const char *sublibname, const char *variableName,
const char *metatableName, const luaL_Reg *metatableFuncs, int defaultValue)
{
int isLibnameNil;
int isSubnameNil;
lua_getglobal(L, libname);//get the libname
isLibnameNil = lua_isnil(L, -1);//check to see if it exists
if(isLibnameNil)//if it doesn't exist, create a new one
{
lua_pop(L, 1);//pop off the nil
lua_newtable(L); // create 'libname' table
}
// no sublib: just import our library functions directly into lib and we're done
if (sublibname == NULL)//if we want the functions at the lib level then just set the functions
{
lua_pushstring(L, variableName);//push the variable name
lua_pushnumber(L, defaultValue);//push the default value on the stack
lua_rawset(L, -3);//add the variable to the table (rawset is like settable but doesn't call __index)
luaL_newmetatable(L, metatableName);//create the metatable
luaL_setfuncs(L, metatableFuncs, 0);//set the metatable functions for __newindex and __index
lua_setmetatable(L, -2);//set the metatable to the libtable
}
// otherwise we need to create a table for the sublibname, import functions to it, add to parent lib.
else
{
lua_getfield(L, -1, sublibname);//see if the sublibname is under the global libname
isSubnameNil = lua_isnil(L, -1);//is it a nil
if(isSubnameNil)//if it is, then we need to create the sublibname
{
lua_pop(L, 1);//pop off the nil
lua_newtable(L);//creates the new sublibname table
}
lua_pushstring(L, variableName);//push the variable name
lua_pushnumber(L, defaultValue);//push the default value on the stack
lua_rawset(L, -3);//add the variable to the table and push it (rawset is like settable but doesn't call __index)
luaL_newmetatable(L, metatableName);//create the metatable
luaL_setfuncs(L, metatableFuncs, 0);//add the metamethods
lua_setmetatable(L, -2);//set the metatable to the sublibname
if(isSubnameNil)
lua_setfield(L, -2, sublibname);//now we need to add the sublibname to the libname
}
if(isLibnameNil)
lua_setglobal(L, libname);//set the global name if it was new
else
lua_pop(L, 1);
}
次に、私の中でmain()
次のような関数を呼び出します。
execContext = luaL_newstate();
//adding lua basic library
luaL_openlibs(execContext);
//now register all the functions with Lua
registerFunctions(execContext, "orc", "chief", Orc_Module);
registerFunctions(execContext, "orc", "pawn", Orc_Module);
registerFunctions(execContext, "elf", "wood", Elf_Module);
//now register all the variables with Lua
registerIntegerVariable(execContext, "orc", "chief", "hp", "chief_meta", orcChief_metareg, 0);
コードを実行してLuaスクリプトでポンピングするorc.chief.attack()
と、OrcAttack()
関数が呼び出されますが、関数orc.chief.hp = 100
は呼び出されませんorcChief__newindex()
。registerFunctions
彼らが何らかの形で干渉していてregisterIntegerVariable
、それだけではまだorcChief__newindex().
アイデアを引き起こさない場合に備えて、私は電話をコメントアウトしましたか?