简体   繁体   中英

How Create Lua Table of Userdata metatable using C API

I Want Create a Table Like This, a Table contains Player Userdata

PlayerList = { player1, player2, ...}

small part my code like this

int Player::GetLocal(lua_State* L){
    auto p = lua_newuserdata(L, sizeof(NativePlayer));
    new (p) NativePlayer();
    p->data = global::get_local();
    luaL_getmetatable(L, "PlayerMetaTable");
    lua_setmetatable(L, -2);
    return 1;
}

int Player::ToList(lua_State* L) {
    lua_newtable();
    GameLogic* gameLogic = global::get_game_logic();

    for (auto it = gameLogic->PlayerList.begin(); it != gameLogic->PlayerList.end(); ++it) {
        lua_pushinteger(L, index);
        auto p = lua_newuserdata(L, sizeof(NativePlayer));
        new (p) NativePlayer();
        p->data = *it;
        luaL_getmetatable(L, "PlayerMetaTable");
        lua_setmetatable(L, -4);
        lua_settable(L, -3);
    }

    return 1;
}

the problem is the data type in the table is not NativePlayerMetatable

instead PlayerList Becomes NativePlayerMetatable

I want the PlayerList to remain a table, and its members are NativePlayerMetatable

currentPlayer = Player.GetLocal()
PlayerList = Player.ToList()

print(currentPlayer)
print(PlayerList[0])
print(PlayerList[1])
print(PlayerList)

Output:

PlayerMetaTable: 000002607203F590
userdata: 0000026079E901D8
userdata: 0000026079EA1A08
PlayerMetaTable: 000002607203F7FF

The Output I want

PlayerMetaTable: 000002607203F590
PlayerMetaTable: 0000026079E901D8
PlayerMetaTable: 0000026079EA1A08
table: 000002607203F7FF

At the point where you call lua_setmetatable(L, -4) in Player::ToList , you have added four objects to the stack. When things are added to the stack, they go on top. We can look backwards to see what's on the stack. Starting from the top, we have first the metatable pushed by luaL_getmetatable , second the player userdata pushed by lua_newuserdata , third the index pushed by lua_pushinteger , and fourth the player list pushed by lua_newtable . (And, none of these values have be popped from the stack yet.)

(In general, we might worry about additional values pushed by previous iterations of the loop, but your loop pushes three values and also pops three values, so no values from any previous iteration will remain -- this is usually good, as a loop that pushes more values than it pops might eventually overflow unless you grow the stack, and a loop that pops more values than it pushes might underflow.)

Negative indices count backwards from the top of the stack. So, again at the point of the lua_setmetatable(L, -4) call, -1 would refer to the metatable, -2 to the player userdata, -3 to the index, and -4 to the player list. Because you are passing -4 , you are assigning the metatable to the player list. To assign the metatable to the player userdata, you would use index -2 instead.

If you find negative indices hard to keep track of, you could consider using positive indices instead. When using positive indices, you may not want to use numbers directly as you may not know the size of the stack to begin with. (For example, in a C function called directly via Lua, which is probably the case for the functions you have exhibited, the stack will initially contain any arguments that were passed to the function, and it would be sloppy to assume that no parameters were passed without checking, even if you don't expect parameters.) You can use lua_gettop to find the index of the element at the top of the stack. Eg

lua_newtable(L);
const int list_index = lua_gettop(L);

... and later...

    auto p = lua_newuserdata(L, sizeof(NativePlayer));
    const int player_index = lua_gettop(L);
    new (p) NativePlayer();
    p->data = *it;
    luaL_getmetatable(L, "PlayerMetaTable");
    lua_setmetatable(L, player_index);
    lua_settable(L, list_index);

But, this does not mean you can ignore the stack altogether as, eg you need to know the top of the stack when you return (although a sloppy implementation could push another copy of the value it wants to return just before returning), and many of the API functions like lua_setmetatable and lua_settable deal directly with values on top of the stack (even if they also take indices).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM