Lua库如何实现对象字段与实例方法共同生效的技术问询
问题根因
你自定义的__index元方法playerget在没有匹配到next/prev/obj等属性字段时直接返回0,Lua会直接判定字段不存在,不会自动去userdata的元表中查找你预先注册的AddCollisionObjHook等实例方法。当__index被设置为C函数而非元表自身时,所有字段查找逻辑完全由这个C函数控制,没有默认的元表 fallback 逻辑。
修复方案
1. 修改playerget函数的未匹配分支
在自定义属性匹配失败后,主动去元表中查找对应的方法字段,存在则返回该字段,否则再返回查找失败:
static int playerget(lua_State *L) { Player *player = *CHECKPLAYER(L, 1); const char *field = luaL_checkstring(L, 2); if (!strcmp(field, "next")) { if (!player->next) lua_pushnil(L); else PushUserdata(player->next, "player"); } else if (!strcmp(field, "prev")) { if (!player->prev) lua_pushnil(L); else PushUserdata(player->prev, "player"); } else if (!strcmp(field, "obj")) { if (!player->obj) lua_pushnil(L); else PushUserdata(player->obj, "wobj"); } // 新增:匹配元表中的实例方法 else { lua_getmetatable(L, 1); lua_getfield(L, -1, field); if (!lua_isnil(L, -1)) return 1; return 0; } return 1; }
2. 修正全局库名不匹配问题
你C代码中注册的全局库名为player,但测试脚本里调用的是playerlib.head(),两者不一致需要统一:
- 要么将C代码中的
lua_setglobal(L, "player");修改为lua_setglobal(L, "playerlib"); - 要么将测试脚本改为
me = player.head()
修改后即可同时支持me.next这类属性访问和me:AddCollisionObjHook()这类实例方法调用,不需要调整playerlib_f和playerlib_m的注册逻辑。
内容的提问来源于stack exchange,提问作者user1054922
相关产品推荐
相关产品推荐

