简体   繁体   English

是否可以将完整的“路径”保存到C函数中的Lua表字段?

[英]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: 如果我在Lua中有这样的全局对象:

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 . 我的问题是关于luaL_reflua_rawgetilua_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: 我可以使用luaL_ref来保存每个stat的路径,以避免在堆栈上显式调用所有stat ,如下所示:

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. 请注意, v2将所有已保存的引用调用到堆栈上。 Does that work? 那样有用吗?

EDIT: In light of the answer by @Nicol Bolas, I want to propose a v3 . 编辑:根据@Nicol Bolas的回答,我想提出一个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. 注册表是Lua状态的一部分,因此只要这些表在注册表中,它们就必须存在。 So any objects referenced by them will exist until you deregister them or close the Lua state. 因此,它们所引用的任何对象都将存在,直到您注销它们或关闭Lua状态为止。

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. 保存stat_1的值将保存为当前值,而不是可能更改为的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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