[英]Lua C API code not calling __newindex functions but calling other functions
I have written some code to separate registering custom functions and the __newindex
and __index
functions into 2 separate functions. 我编写了一些代码来将自定义函数和
__newindex
和__index
函数分别注册到2个单独的函数中。 The goal of my code is to have functions and variables visible to the Lua script writer that are organized based upon sublevels of specificity. 我的代码的目标是让Lua脚本编写器可以看到基于特异性子级组织的函数和变量。 For example, the user would have available the following commands:
例如,用户可以使用以下命令:
orc.chief.attack();
orc.chief.flee();
orc.chief.hp = 100;
orc.pawn.attack();
elf.wood.attack();
elf.wood.hp = 200;
So basically a system with 2 tiers and then a function call or a variable. 所以基本上是一个有2层,然后是函数调用或变量的系统。 If I understand Lua correctly, that is a metatable in a table in a table.
如果我正确理解Lua,那就是表格中的表格。 When the user sets the variable, it should trip a
__newindex
call (not only to handle setting the value but to access a physical object that will animate through motors). 当用户设置变量时,它应该
__newindex
调用(不仅要处理设置值,还要访问将通过电机设置动画的物理对象)。 I also assume that the chief table in the table orc
just sees lots of functions assigned to it regardless whether it is attack
or __newindex
. 我还假设表
orc
中的主表只是看到了很多分配给它的函数,无论它是attack
还是__newindex
。 To make it easier to add new variables and functions as the code develops, I have created 2 functions: one to create a function and one to create a variable. 为了便于在代码开发时添加新的变量和函数,我创建了两个函数:一个用于创建函数,另一个用于创建变量。 The function
create
just registers the functions and the variable create
just makes a new table element and registers the functions for __newindex
and __index
. 函数
create
只是注册函数而变量create
只是创建一个新的表元素并注册__newindex
和__index
的函数。 Below is the code: 以下是代码:
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);
}
Then, in my main()
I call the functions like this: 然后,在我的
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);
When I run the code and pump in Lua scripts, orc.chief.attack()
calls my OrcAttack()
function but orc.chief.hp = 100
never calls my orcChief__newindex()
function. 当我在Lua脚本中运行代码和泵时,
orc.chief.attack()
调用我的OrcAttack()
函数,但orc.chief.hp = 100
从不调用我的orcChief__newindex()
函数。 I have even commented out the registerFunctions
calls in case they were interfering somehow and just the registerIntegerVariable
by itself still won't trigger the orcChief__newindex().
我甚至已注释掉
registerFunctions
调用,以防它们以某种方式干扰,而registerIntegerVariable
本身仍然不会触发orcChief__newindex().
Any ideas? 有任何想法吗?
__newindex
is not called when you set a field in a table. 在表中设置字段时,不会调用
__newindex
。 It is called when you set a new field in a table. 在表中设置新字段时调用它。 If the field already exists,
__newindex
will not be called. 如果该字段已存在,则不会调用
__newindex
。
If you want __newindex
to be called for every set operation on a table, you can't allow set operations to actually modify that table. 如果要为表上的每个集合操作调用
__newindex
,则不能允许集合操作实际修改该表。 This is generally done by creating an empty table, called a proxy table, which the user uses. 这通常通过创建用户使用的称为代理表的空表来完成。 The proxy table is actually empty and must always remain so;
代理表实际上是空的,必须始终保持不变; you intercept all of the get and set calls, piping them to an internal table that the user never sees don't have access to.
您拦截所有get和set调用,将它们传递给用户从未看到过无法访问的内部表。
Or you use some userdata instead of a table. 或者您使用一些userdata而不是表。
__newindex
is always called for them. 总是为它们调用
__newindex
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.