Lua / c++问题处理命名数组条目

我正在尝试编写一些C++类与LUA进行接口交互,但是我对以下内容感到困惑:

在以下示例中:Wherigo.ZCommand返回“Command”对象,而zcharacterFisherman.Commands是Command对象的数组:

使用以下LUA代码,我理解它并且它可以正常工作(在zcharacterFisherman.Commands C++ set newindex函数中,luaL_getn返回3):

zcharacterFisherman.Commands = {
  Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
  Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
  Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
}

但是当使用以下LUA代码定义数组时,稍微有些不同的语法,luaL_getn返回0。

zcharacterFisherman.Commands = {
  Talk = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
  Talk2 = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
  Talk3 = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
}

所有对象都在C++中定义,而C++对象持有所有对象成员,因此我正在尝试将LUA连接到这些C++对象。这是否足够,还是需要发布一些我的代码?

原文链接 https://stackoverflow.com/questions/947802

点赞
stackoverflow用户78006
stackoverflow用户78006

luaL_getn 函数用于获取 Lua 中 数组 的最高数字元素。数组是一个只有整数索引的表。当你在 Lua 中定义一个表(第一个例子),如果没有明确地设置索引,你将得到一个包含元素 1、2 和 3 的数组。自然地, luaL_getn 在此处返回 3。luaL_getn 并没有定义返回表中元素个数的函数,它定义了返回表中最高数字索引的函数(参见 http://www.lua.org/manual/5.1/manual.html#pdf-table.maxn)。

第二个例子没有使用数字索引,因此该表不是 Lua 数组 -- 它更像是哈希表。由于 luaL_getn 仅适用于真正的数组,因此你不会指望它在这里起作用。

不幸的是,没有简单的方法来获取表中元素的数量(lua_objlen 解决了一个相关的问题,但没有解决这个问题)。唯一的方法是:

  1. 始终使用数组表示法。用其他任何东西做为表中键的索引。这样可以获得很多加速效果。
  2. 当你想知道表的大小时,遍历它并计算元素的数量。语言没有提供获取完整表大小的一行代码方法,因为通用表是使用哈希实现的,不跟踪它们的元素计数。
2009-06-04 00:05:02
stackoverflow用户110672
stackoverflow用户110672

Lua 表格(tables)即可以结合哈希表和标准数组。

你的第一个示例等同于:

zcharacterFisherman.Commands = {
  [1] = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
  [2] = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
  [3] = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
}

getn 帮助你找到空的数字项。如果 t[1]==nil,则 table.getn(t) == 0。在你的第二个示例中,你没有对 zcharacterFisherman.Commands[1] 进行赋值,这就是你得到 0 的原因。

zcharacterFisherman.Commands = {
  [1] = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
  [2] = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
  [3] = Wherigo.ZCommand{a="Talk", b=false, d=true, c="Nothing available"},
}
zcharacterFisherman.Commands[1]=nil
print(table.getn(zcharacterFisherman.Commands))

这段代码将打印 0(或可能是 >=3 的数字)。

通常,无法直接获取表格哈希表部分的元素数量,除非遍历它们(例如,使用 pairs())。

2009-06-04 00:12:41
stackoverflow用户68204
stackoverflow用户68204

Lua 正确

你的第一个例子形成一个包含三个条目的表,这些条目的索引分别为 1、2 和 3,没有一个是显式指定的。在这种情况下, table.maxn()# 运算符和 lua_objlen() 同意,表中有三个数组元素。

你的第二个例子形成一个包含三个条目的表,这些条目的索引分别为 "Talk"、"Talk2" 和 "Talk3",都是显式指定的,但没有一个是整数。在这种情况下, table.maxn()# 运算符和 lua_objlen() 同意,表中没有数组元素。

为什么这是正确的答案?

Lua 的 table 是一个可将任何类型的值(除了 nil)映射到任何类型的值(同样除了 nil)的关联数组。Lua 中没有其他通用容器类型,因此表格用于基本上所有东西。实现不是 Lua 规范的一部分,但实际上表格被索引为哈希表,并且没有键的自然排序。

然而,表的常见用例是作为行为类似于传统数组的容器。这种容器具有连续的整数索引,并且可以按顺序迭代。表的实现使得对于从 1 开始的整数键特别高效。表格中的这些条目被物理分配为连续数组,并且键既不被哈希也不被存储。这节省了存储空间,既避免了分配开销,又不完全存储一些键。这还节省了运行时间,因为访问是通过直接计算而不是通过计算哈希并验证匹配值来完成的。

由于数组只是表,表初始化语法已被设计为使该情况易于理解和清晰,同时还支持键为字符串且是有效标识符的常见用例。

Lua 5.1 vs Lua 5.0

在当前版本的 Lua(5.1.4,但这适用于所有 5.1 版本)中,Lua 5.0 函数 table.getn()table.setn()luaL_getn()luaL_setn() 均已被弃用,将表字段 n 用于数组以表示其数组长度的常见用法也被弃用。table.getn() 函数被 # 运算符代替,luaL_getn()lua_objlen() 代替。由于 Lua 现在在幕后管理数组大小,没有等效的 setn() 函数。

# 运算符在表上定义为返回一个整数,使得用下一个较大的整数索引来索引表返回 nil。对于空数组(例如 a = {}),它返回 0,因为 a[1] == nil。对于普通数组,它返回使用的最大索引。但是,如果一个数组有空隙(缺少元素),那么它可以返回任何空隙之前的索引或使用的最后一个索引。如果需要实际上使用的最大整数索引,则可以使用新函数 table.maxn(),但是必须遍历所有表条目以找到该最大值,因此仅在使用 # 无法时才应使用它。

这导致了现在常见的一个惯用语,用于向数组添加元素:a[#a+1] = "some new value"。与 table.insert() 扩展表的惯用语现在经常被推荐为替代。

2009-06-04 21:30:54