c - luaL_setmetatable() 覆盖其他值的元表

标签 c lua lua-5.3

我的项目中有不同的元表。但是,如果我创建一个值 A 并分配元表“X”并创建第二个值 B 并附加元表“Y”,A 也会获得 Y 元表!下面是一个简化的 C 函数用于演示:

#include <errno.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
// shoudl create t["obj"] = <userdata> with metatable = "Obj" but gets "OtherType"
int create_table_with_object(lua_State *L)
{
        lua_newtable(L);
        lua_pushlightuserdata(L, (void*)0x1234);
        luaL_setmetatable(L, "Obj"); // This Type is already registered with lua_newmetatable()
        lua_setfield(L, -2, "obj");

        luaL_newmetatable(L, "OtherType");
        lua_pushinteger(L, 70);
        lua_setfield(L, -2, "ICameFromOtherType");
        lua_pop(L, 1); // just a dummy table

        // If we create another userdata object, the first one
        // gets the same type as this one!
        // Obj -> changes to "OtherType"
        // ### CRITICAL SECTION STRT ###
        lua_pushlightuserdata(L, (void*)0x5555);
        luaL_setmetatable(L, "OtherType");
        lua_setglobal(L, "JustADummyObj"); // this removes the value from the stack!
        // ### CRITICAL SECTION END  ###

        return 1;
}

int main(void)
{
        lua_State *L = luaL_newstate();
        luaL_openlibs(L);

        luaL_loadfile(L, "bug.lua");

        lua_pushcfunction(L, create_table_with_object);
        lua_setglobal(L, "create_table_with_object");

        luaL_newmetatable(L, "Obj");
        lua_pop(L, 1);

        int error;
        if(error = lua_pcall(L, 0, 0, 0))
        {
                fprintf(stderr, "Fatal error: \n");
                fprintf(stderr, "%s\n", lua_tostring(L, -1));
                return 1;
        }

        lua_close(L);

        return 0;
}

Lua代码:

local a = create_table_with_object()
print(getmetatable(a.obj).__name)

输出是“OtherType”,但它应该是“Obj”。看来第二次调用 lua_setmetatable() 会覆盖其他值的表?!

最佳答案

好的,解决了! Lua 中的 lightuserdata 共享一个元表(而不是每个值一个元表)。因此,更改 lightuserdata 值的表会更改所有其他 lightuserdata 值!

关于c - luaL_setmetatable() 覆盖其他值的元表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29750993/

相关文章:

c - `_Generic` 类型作为输出

用于嵌入式系统的 LuaJIT 或 eLua?

date - 在lua中来回UTC日期

lua 元表错误或功能?

lua - Zerobrane 不访问环境

Lua:本地package.path

c - 制作一个字符数组

c - libsigsegv 和响应堆栈溢出

c - 提供相对路径时加载纹理将不起作用

string - 在 Lua 中使用 "("?) 与 string.find 及其返回值