2016-08-13 1 views
1

어떤 객체의 메타 테이블 이름을 조회하고 싶습니다.Lua : userdata 객체의 메타 테이블 이름 쿼리하기

내가 어떤 메타 테이블은 다음과 같은 등록했다고 생각해

Object obj; // some C object 

luaL_newmetatable(lua, "my_metatable"); // it's empty 

lua_pushlightuserdata(lua, &obj); 
luaL_setmetatable(lua, "my_metatable"); 
lua_setglobal(lua, "obj_"); 

here 상태가 luaL_newmetatable 듀얼 협회, 즉 그것은 키와 테이블에 키와 테이블로 이름을 사용 않습니다 그쪽으로 문서이라는 이름으로 이 nil을 반환, 불행하게도, 그것은 작동하지 않았다,

lua_pushcfunction(lua, getMTName); 
lua_setglobal(lua, "getMTName"); 

그러나 : 그래서,이 지식으로, 나는 다음과 같이 내 목표 달성 할 수있는 생각 :

int getMTName(lua_State *L) 
{ 
    lua_getmetatable(L, 1); // get the metatable of the object 
    lua_rawget(L, LUA_REGISTRYINDEX); // since the metatable is a key 
             // to its name in registry, use 
             // it for querying the name 
    return 1; // the bottom of the stack is now the name of metatable 
} 

을하고 싶은 등록. 그래서, 나쁘지 않아? 여기

, (C++에서) 약간의 전체 소스 코드 :

extern "C" 
{ 
#include <lua.h> 
#include <lualib.h> 
#include <lauxlib.h> 
} 

#include <iostream> 

struct Object { 
    int x; 
}; 

int getMTName(lua_State *L) 
{ 
    lua_getmetatable(L, 1); 
    lua_rawget(L, LUA_REGISTRYINDEX); 
    return 1; 
} 

int main(int argc, char **argv) 
{ 

    lua_State *L =luaL_newstate(); 
    luaL_openlibs(L); 

    Object obj; 

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

    luaL_newmetatable(L, "my_metatable"); 

    lua_pushlightuserdata(L, &obj); 
    luaL_setmetatable(L, "my_metatable"); 
    lua_setglobal(L, "obj_"); 

    int e = luaL_dostring(L, "print(getMTName(obj_))"); 

    if (e) 
    { 
     std::cerr << "ERR: " << lua_tostring(L, -1) << std::endl; 
     lua_pop(L, 1); 
    } 

    return 0; 

} 

출력 nil입니다. 내 루아 버전은 5.3입니다.

답변

1

이제 알았습니다. https://www.lua.org/source/5.3/lauxlib.c.html#luaL_newmetatable에서 소스 코드를 살펴보면,이 이중 연관이 레지스트리에서 이름에 대한 키로 테이블을 사용하는 대신 metatable에서 "__name"을 사용하여 완료되었음을 알게되었습니다. 이 동작은 루아 5.3부터 시작됩니다.

샘플 코드 :

extern "C" 
{ 
#include <lua.h> 
#include <lualib.h> 
#include <lauxlib.h> 
} 

#include <iostream> 

struct Object { 
    int x; 
}; 

int getMTName(lua_State *L) 
{ 
    lua_getmetatable(L, 1); 
    lua_pushstring(L, "__name"); 
    lua_rawget(L, 2); 
    return 1; 
} 

int main(int argc, char **argv) 
{ 

    lua_State *L =luaL_newstate(); 
    luaL_openlibs(L); 

    Object obj; 

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

    luaL_newmetatable(L, "my_metatable"); 

    lua_pushlightuserdata(L, &obj); 
    luaL_setmetatable(L, "my_metatable"); 
    lua_setglobal(L, "obj_"); 

    int e = luaL_dostring(L, "print(getMTName(obj_))"); 

    if (e) 
    { 
     std::cerr << "ERR: " << lua_tostring(L, -1) << std::endl; 
     lua_pop(L, 1); 
    } 

    return 0; 

} 
+1

루아 5.0 (PIL의 무료 온라인 버전에 포함 루아 버전) 원래 언급 한 바와 같이 이중 결합을한다. [here] (https://www.lua.org/source/5.0/lauxlib.c.html#luaL_newmetatable)를 참조하십시오. 최신 루아 버전은 더 이상 그렇게하지 않습니다. – siffiejoe

+0

@시피에 저에게 감사드립니다. –

관련 문제