我有一个具有某种元表类型的Lua userdata对象(例如"stackoverflow.test"
).从C代码,我希望能够确切地检查它是什么类型,并根据结果表现不同.是否有一个非常方便的功能(相当像luaL_checkudata
,但如果答案不是你想要的,没有错误)让我查询userdata的metatable类型名称?如果没有,我想我需要使用lua_getmetatable
,但是我有点不清楚我如何确定刚刚添加到堆栈中的metatable的名称.
只是为了澄清:我正在使用Lua 5.1,其中luaL_checkudata的行为被改变了.据我所知,在5.0中它并不习惯错误.
您始终可以在metatable中存储标记字段,其中包含模块特有的轻用户数据值.
static const char *green_flavor = "green"; ... void my_setflavor(lua_State *L, void *flavor) { lua_pushlightuserdata(L,flavor); lua_pushlstring(L,"_flavor"); lua_rawset(L,-3); } void my_isflavor(lua_State *L, void *flavor) { void *p = NULL; lua_pushlstring(L,"_flavor"); lua_rawget(L,-2); p = lua_touserdata(L,-1); lua_pop(L,1); return p == flavor; }
然后,您可以使用my_setflavor(L,&green_flavor)
在堆栈顶部设置表的_flavor字段,并my_isflavor(L,&red_flavor)
测试堆栈顶部表的_flavor字段.
使用这种方式,_flavor字段只能接受可以由范围中具有符号green_flavor的模块中的代码创建的值,并且查找字段并测试其值仅需要除了检索metatable本身之外的一个表查找.请注意,变量green_flavor的值无关紧要,因为实际上只使用了其地址.
有几个不同的风味变量可用作sentinal值,_flavor字段可用于区分几个相关的元表.
所有这些都说,一个自然的问题是"为什么要这样做?" 毕竟,metatable可以轻松地包含获得适当行为所需的所有信息.它可以很容易地保存函数和数据,并且可以从C和Lua中检索和调用这些函数.