2017-04-08 6 views
1

私はこのようなLuaのではグローバルオブジェクトがある場合:完全な "パス"をC関数の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 

を私の質問を約luaL_reflua_rawgeti、およびlua_getfieldです。

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; 
} 

v2その呼び出しスタックに保存された参照のすべてを:私はこのように、スタック上にそれらのすべてを呼び出して、明示的に回避するために、各statへのパスを保存するためにluaL_refを使用することができます。それは動作しますか?

EDIT: @Nicol Bolasの答えに照らして、私はv3を提案したいと思います。テーブルとサブテーブルがガベージコレクションされることはありませんが、その値は常に更新されます(サブテーブルの構造全体をツリー、各サブテーブル、ブランチ、各基本値が葉であると想像してください)。実行中も同じですが、葉が更新されます)。

//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; 
} 

答えて

2

これは可能ですが、基本的にはガベージコレクションの形式をあきらめることになります。レジストリはLua状態の一部です。レジストリ内にある限り、それらは存在する必要があります。そのため、それらのオブジェクトが参照するオブジェクトは、登録を解除するか、Luaの状態を閉じるまで存在します。

「パス」は実際に保存されていません。これらの場所にあるテーブルに格納されている実際の値を保存しています。したがって、テーブルの値が変更されている場合、レジストリに格納されている内容は更新されません。 stat_1の値を保存すると、現在の値になりますが、値は変更されません。

+0

私は見る!このような明確な答えをありがとうございます。あなたは '' stat_group_1'に ''パスを保存する ''と '' lua_getfield''を使って '' stat_1''を呼び出すことができると思いますか?なぜなら、フィールドの1つが呼び出されるたびにテーブルが再作成される可能性が高いからです。私はそれが更新されただけだと思う​​。テーブルをツリーとして考えると、リーフ(実際の値)は更新されますが、ブランチ(サブテーブル)は実行中は同じままです。私はそれをテストする必要があります。しかし、そうであると仮定すると、LuaとCが値のツリーを共有することは可能でしょうか? – FinnTheHuman

+0

@FinnTheHuman:それはすべてLuaスクリプトが何をするかによって異なります。テーブルはLuaの値なので、新しいテーブルに置き換えることができます。しかし、整数値の場合と同じように、*それらを置き換えるだけで置き換えられます。 'global_object.stat_group_1.stat_1 = 1'がある値を別の値に置き換えるのと同様に、' global_object.stat_group_1 = {} 'もそのテーブルエントリの現在の値を何も含まない新しいテーブルに置き換えます。あなたのLuaスクリプトが何をしているのかどうかはすべて問題です。 –

+0

私は参照してください。ありがとうございました。 – FinnTheHuman

関連する問題