2016-08-13 8 views
1

あるオブジェクトのメタテーブルの名前をクエリしたいと思います。Lua:ユーザデータオブジェクトのメタテーブルの名前を問い合わせる

は、私は次のように登録されたいくつかのメタテーブルを持っていることを考えてみましょう:luaL_newmetatable THA

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状態は、二重の関連付けを行い、すなわちそれは、テーブルにキーとキーとしてテーブルとして名を使用していますという名前になります。

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 
} 

、それが好き登録:だから、この知識で、私は次のように私の目標を達成することができます思っ

lua_pushcfunction(lua, getMTName); 
lua_setglobal(lua, "getMTName"); 
をしかし、残念ながら、それはそれは nilを返され、動作しませんでした。それで、私の悪いのは何ですか?ここで

、(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のソースコードを見ると、この二重関連付けは、レジストリでその名前のキーとしてtableを使用するのではなく、メタ可能な "__name"を使って行われていることに気付きました。この動作は、Lua 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

(PILの無料のオンライン版でカバーLuaのバージョンである)のLua 5.0は、あなたが最初に述べたように、二重の関連付けを行います。 [here](https://www.lua.org/source/5.0/lauxlib.c.html#luaL_newmetatable)を参照してください。新しいLuaのバージョンでは、それ以上のことはしません。 – siffiejoe

+0

@シフィエジョー情報をありがとうございます。 –

関連する問題