C++绑定vec3到Lua时metatable属性赋值索引报错求助
问题根因
你遇到的问题由3个核心错误共同导致:
- 未给vec3的metatable注册
__newindex元方法:Lua对userdata做属性赋值时,找不到__newindex就会尝试直接给userdata新增字段,而userdata默认不支持直接添加字段,直接抛出索引异常 - 原
__index逻辑错误:你直接把metatable本身设为__index,同时在metatable里写死了x=3.4,你测试时读取testvec.x拿到的是固定的3.4,根本不是C++实例里存储的初始化值17,属于巧合式正常 _set_x、_get_x实现逻辑错误:尝试对userdata调用lua_getfield/lua_setfield操作字段,userdata不是Lua表,没有字段存储能力,必然触发异常
修复步骤
1. 修正属性读写函数
直接操作C++侧的Vector3实例内存,不要尝试读写Lua侧的字段:
static int _get_x(lua_State* L) { Vector3* v = *reinterpret_cast<Vector3**>(luaL_checkudata(L, 1, LUA_Vector3)); lua_pushnumber(L, v->x); return 1; } static int _set_x(lua_State* L) { Vector3* v = *reinterpret_cast<Vector3**>(luaL_checkudata(L, 1, LUA_Vector3)); v->x = luaL_checknumber(L, 2); return 0; } // 同理实现_get_y、_set_y、_get_z、_set_z
2. 实现通用的__index和__newindex元方法
处理属性的读写路由:
static int _index(lua_State* L) { const char* key = luaL_checkstring(L, 2); if (strcmp(key, "x") == 0) return _get_x(L); if (strcmp(key, "y") == 0) return _get_y(L); if (strcmp(key, "z") == 0) return _get_z(L); // 匹配不到属性时查找metatable里的方法(比如get_x、set_x) lua_getmetatable(L, 1); lua_getfield(L, -1, key); return 1; } static int _newindex(lua_State* L) { const char* key = luaL_checkstring(L, 2); if (strcmp(key, "x") == 0) return _set_x(L); if (strcmp(key, "y") == 0) return _set_y(L); if (strcmp(key, "z") == 0) return _set_z(L); luaL_error(L, "vec3 has no attribute '%s'", key); return 0; }
3. 修正vec3注册逻辑
替换错误的__index配置,新增__newindex注册,删除无用的固定x赋值:
static void register_vector3(lua_State* L) { lua_register(L, LUA_Vector3, lua_vec3::_new); luaL_newmetatable(L, LUA_Vector3); lua_pushcfunction(L, lua_vec3::_delete); lua_setfield(L, -2, "__gc"); // 替换原__index配置 lua_pushcfunction(L, lua_vec3::_index); lua_setfield(L, -2, "__index"); // 新增__newindex配置 lua_pushcfunction(L, lua_vec3::_newindex); lua_setfield(L, -2, "__newindex"); // 删掉这行无用代码 lua_pushnumber(L, 3.4); lua_setfield(L, -2, "x"); lua_pushcfunction(L, lua_vec3::_set_x); lua_setfield(L, -2, "set_x"); lua_pushcfunction(L, lua_vec3::_get_x); lua_setfield(L, -2, "get_x"); // 同理注册y、z的get/set方法 lua_pop(L, 1); }
修复后你的Lua测试代码即可正常读写vec3的x/y/z属性。
内容的提问来源于stack exchange,提问作者Johnny_02
相关产品推荐
相关产品推荐

