gpt4 book ai didi

c - Lua C API代码不调用__newindex函数而是调用其他函数

转载 作者:行者123 更新时间:2023-11-30 14:22:39 25 4
gpt4 key购买 nike

我编写了一些代码来分隔注册自定义函数和 __newindex__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只是看到分配给它的很多功能,无论它是否是 attack__newindex 。为了在代码开发时更容易添加新变量和函数,我创建了 2 个函数:一个用于创建函数,一个用于创建变量。函数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().有什么想法吗?

最佳答案

当您在表中设置字段时,不会调用

__newindex。当您在表中设置字段时会调用它。如果该字段已经存在,则不会调用__newindex

如果您希望为表上的每个集合操作调用 __newindex,则不能允许集合操作实际修改该表。这通常是通过创建一个空表(称为代理表)供用户使用来完成的。代理表实际上是空的,并且必须始终保持如此;您拦截所有 get 和 set 调用,将它们通过管道传输到用户永远看不到且无权访问的内部表。

或者您使用一些用户数据而不是表。 __newindex 总是为它们调用。

关于c - Lua C API代码不调用__newindex函数而是调用其他函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13612268/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com