创建引用的表元素

时间:2014-08-17 21:34:34

标签: c lua

我在C中创建了一个或多或少复杂的表。现在我想在树的较低层创建一个引用。这可能吗?

点子:

ELEM000 +--> ELEM010
        +--> ELEM020 +--> ELEM120
        |            +--> **ELEM121**
        |            +--> ELEM122
        +--> ELEM030 +--> ELEM130
        |            +--> ELEM131
        |            +--> ELEM132
        +--> **ELEM121**

ELEM121也应该在上面一层可见,即作为参考

我添加了一个我想要的例子..

void PushL(lua_State *L, const char * str) {
char s[255];
strcpy(s, "ELEM"); strcat(s, str);   lua_pushstring(L, s);  // key
strcpy(s, "Value"); strcat(s, str);  lua_pushstring(L, s);  // value
lua_settable(L, -3);
}
void MakeTable( lua_State *L )
{
lua_pushstring(L, "TBL0");  // name of sub-table

lua_createtable(L, 0, 0);
lua_checkstack(L, 3);
{

PushL(L, "000");

lua_pushstring(L, "TBL1");

lua_createtable(L, 0, 0);
lua_checkstack(L, 3);
{
  PushL(L, "010");
  PushL(L, "020");

  lua_pushstring(L, "TBL2");

  lua_createtable(L, 0, 0);
  lua_checkstack(L, 3);
  {
    PushL(L, "120");
    PushL(L, "121");
    PushL(L, "122");
    lua_settable(L, -3);
  }
  PushL(L, "030");

  lua_pushstring(L, "TBL3");

  lua_createtable(L, 0, 0);
  lua_checkstack(L, 3);
  {
    PushL(L, "130");
    PushL(L, "131");
    PushL(L, "132");
    lua_settable(L, -3);
  }

  lua_settable(L, -3);
}

lua_pushstring(L, "ELEM121");
lua_pushstring(L, "SHOULD BE A REFERENCE TO ELEM121");
lua_settable(L, -3);
}
lua_setglobal(L,"____myTable");
}

1 个答案:

答案 0 :(得分:0)

底线:在Lua中,无法引用字段变量,但有多种方法可以实现您想要的效果。

这是C数据结构和Lua数据结构之间的比较。

在C中,你要么:

  1. 在两个地方有一份价值副本

    您也可以在Lua中创建副本。

  2. 或者,在一个地方指向另一个地方的指针。

    在C中,这意味着您必须以不同方式访问它们,一个具有指针参照,另一个没有。

    在Lua中,你可以在一个地方有一个函数,它返回另一个地方的值。这意味着您必须以不同方式访问它们,一个带有函数调用,另一个没有。

  3. 以下等同于只读指针:

    local ELEM000 = { 
      ELEM010 = "ELEM010 value",
      ELEM020 = { 
        ELEM120 = "ELEM120 value",
        ELEM121 = "ELEM121 value",
        ELEM122 = "ELEM122 value" },
      ELEM030 = { 
        ELEM130 = "ELEM130 value",
        ELEM131 = "ELEM131 value",
        ELEM132 = "ELEM132 value" },
      ELEM121 = function(self) return self.ELEM020.ELEM121 end }
    
    print(ELEM000.ELEM020.ELEM121)
    print(ELEM000:ELEM121())
    ELEM000.ELEM020.ELEM121 = ELEM000.ELEM020.ELEM121 .. " updated" 
    print(ELEM000.ELEM020.ELEM121)
    print(ELEM000:ELEM121())
    

    如果你需要一个可写指针,那么就需要另一种方法。


    更新

    可写指针的一种简单方法是添加可选的值参数。这通常用于JavaScript API,但JavaScript具有undefined数据类型的优势。在Lua中,我们必须使用nil,这意味着您无法将nil写为值。

    ELEM121 = function(self, value) 
        if (value ~= nil) then self.ELEM020.ELEM121 = value end 
        return self.ELEM020.ELEM121 
        end
    

    对于真正的读写字段访问,请使用__index和__newindex metatmethods。这要求该字段实际上没有表中的键。索引不存在的字段以进行读取(__index)或写入(__newindex)时会调用元方法。

    local ELEM000 = { 
      ELEM010 = "ELEM010 value",
      ELEM020 = { 
        ELEM120 = "ELEM120 value",
        ELEM121 = "ELEM121 value", -- captured as the initial value
        ELEM122 = "ELEM122 value"}, 
      ELEM030 = { 
        ELEM130 = "ELEM130 value",
        ELEM131 = "ELEM131 value",
        ELEM132 = "ELEM132 value" },
      ELEM121 = nil -- ignored 
    }
    
    setmetatable(ELEM000, { 
      __index = function(base, key) 
          if (key=="ELEM121") then return base.ELEM020.ELEM121 
          else return nil end end,
      __newindex = function (base, key, value) 
          if (key=="ELEM121") then base.ELEM020.ELEM121 = value 
          else rawset(base, key, value) end end })
    
    setmetatable(ELEM000.ELEM020, { 
      ELEM121 = ELEM000.ELEM020.ELEM121, --[[ backing storage for field, 
                                              initialized to existing value]] 
      __index = function(base, key) 
          if (key=="ELEM121") then return getmetatable(base).ELEM121 
          else return nil end end,
      __newindex = function (base, key, value) 
          if (key=="ELEM121") then getmetatable(base).ELEM121 = value 
          else rawset(base, key, value) end end })
    
    -- make sure metamethods will be invoked on these fields  
    rawset(ELEM000, "ELEM121", nil)     
    rawset(ELEM000.ELEM020, "ELEM121", nil)
    

    用法:

    print(ELEM000.ELEM020.ELEM121)
    print(ELEM000.ELEM121)
    
    ELEM000.ELEM020.ELEM121 = ELEM000.ELEM020.ELEM121 .. " updated" 
    print(ELEM000.ELEM020.ELEM121)
    print(ELEM000.ELEM121)
    
    ELEM000.ELEM121 = ELEM000.ELEM121 .. " again" 
    print(ELEM000.ELEM020.ELEM121)
    print(ELEM000.ELEM121)
    

    有各种存储支持字段的地方以及编码元方法的不同风格。这段代码可能过于简洁。而且,如果您愿意,我会留给您使用Lua C API对其进行编码。