You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++绑定vec3到Lua时metatable属性赋值索引报错求助

问题根因

你遇到的问题由3个核心错误共同导致:

  1. 未给vec3的metatable注册__newindex元方法:Lua对userdata做属性赋值时,找不到__newindex就会尝试直接给userdata新增字段,而userdata默认不支持直接添加字段,直接抛出索引异常
  2. 原__index逻辑错误:你直接把metatable本身设为__index,同时在metatable里写死了x=3.4,你测试时读取testvec.x拿到的是固定的3.4,根本不是C++实例里存储的初始化值17,属于巧合式正常
  3. _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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 11:45:05