简体   繁体   中英

Is it possible to save the complete “path” to a Lua table field in a C function?

If I have a global object in Lua like this:

global_object = { }
global_object.stat_group_1 = { }
global_object.stat_group_2 = { }
global_object.stat_group_3 = { }
global_object.stat_group_1.stat_1 = 1 -- value changes with time
global_object.stat_group_1.stat_2 = 2 -- value changes with time
global_object.stat_group_1.stat_3 = 3 -- value changes with time
-- ... and same thing for other stat_groups

My question is about luaL_ref , lua_rawgeti , and lua_getfield . Can I use luaL_ref to save the path to each stat to avoid explicitly calling all of them on the stack, like this:

int global_object_ref;
int stat_group_1_ref;
int stat_1_ref;

//assume this function has been called before any of the get_* functions
int start ( lua_State * L )
{
    lua_getfield ( L, LUA_RIDX_GLOBALS, "global_object" );
    lua_pushvalue ( L, -1 );
    global_object_ref = LuaL_ref ( L, LUA_REGISTRYINDEX );

    lua_getfield ( L, -1, "stat_group_1" );
    lua_pushvalue ( L, -1 );
    stat_group_1_ref = LuaL_ref ( L, LUA_REGISTRYINDEX );

    lua_getfield ( L, -1, "stat_1" );
    lua_pushvalue ( L, -1 );
    stat_group_1_ref = LuaL_ref ( L, LUA_REGISTRYINDEX );

    return 0;
}

//this is the prefered option. I would like this to be possible
int get_stat1_v1 ( lua_State * L )
{
    //stat_1 can have different values in the Lua table at different moments
    lua_rawgeti ( L, LUA_REGISTRYINDEX, stat_1_ref );

    //is this the value of the field stat_1?
    int value_of_stat_1 = lua_tointeger ( L, -1 );

    return 1;
}

//this is an alternative, in case v1 doesn't work. Would this work?
//again, remember stat_1 can have different values at different moments.
int get_stat1_v2 ( lua_State * L )
{
    lua_rawgeti ( L, LUA_REGISTRYINDEX, global_object_ref );
    lua_rawgeti ( L, LUA_REGISTRYINDEX, stat_group_1_ref );
    lua_rawgeti ( L, LUA_REGISTRYINDEX, stat_1_ref );

    //is this the value of the field stat_1?
    int value_of_stat_1 = lua_tointeger ( L, -1 );

    return 1;
}

Note that v2 calls all of saved references the onto the stack. Does that work?

EDIT: In light of the answer by @Nicol Bolas, I want to propose a v3 . If the table and sub-tables are never garbage collected, but their values are constantly updated (Imagine the whole structure of sub-tables as a tree, each sub-table a branch, each fundamental value a leaf. The structure of the tree remains the same during execution, but the leaves get updated).

//this is the v3, where I learned how the Lua registry interacts with C, and propose
//a direct leaf access, but indirect branch access.
int get_stat1_v3 ( lua_State * L )
{
    //can I skip the line bellow and go directly to the next? Or do I have
    //to follow the whole hierarchy of branches?
    lua_rawgeti ( L, LUA_REGISTRYINDEX, global_object_ref );//is this needed?

    //I know I'm repeating myself, but I want to know if the call above
    //is necessary or not. Can I directly cut to the chase by calling this function?
    lua_rawgeti ( L, LUA_REGISTRYINDEX, stat_group_1_ref );

    //Notice that for this to work I'd have to removed the reference to stat_1
    //from the registry of my proven flawed implementation, so I wouldn't
    //freeze and pin down the value of stat_1, which means stat_1_ref gets
    //removed from the code.
    lua_getfield ( L, -1, "stat_1" );

    //is this the dynamically up to date value of the field stat_1?
    int value_of_stat_1 = lua_tointeger ( L, -1 );

    return 1;
}

You could do this, but you'd basically be giving up any form of garbage collection. The registry is part of the Lua state, so as long as those tables are in the registry, they must exist. So any objects referenced by them will exist until you deregister them or close the Lua state.

You aren't really saving "paths". You're saving the actual value stored in the tables at those locations. So what's stored in the registry will not be updated if the table's value is change. Saving the value of stat_1 saved will be the value it currently has, not the value it may change to.

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