【问题标题】:lua userdata with array access and object oriented access?具有数组访问和面向对象访问的lua userdata?
【发布时间】:2013-05-02 21:52:04
【问题描述】:

我正在编写一个“C”用户数据数组结构。 作为 setter 和 getter,我想要正常的数组访问 (u[0] = 1 u[0]),就像这里讨论的那样: [c 数组共享][1]Share Array between lua and C. 为此,我需要将 __index 和 __newindex 设置为 set 并在 c 中获取函数。

另外,我也想要面向对象的访问,“就像 u:mymethod()”。我的麻烦是,我现在需要将 __index 设置为元表本身。

有没有办法同时实现?

【问题讨论】:

  • 为什么你需要你的__index 作为元表?如果你把它们分开会更容易。
  • 我在这里读到:lua.org/pil/28.3.html。但是,是的,我不需要它。

标签: c lua


【解决方案1】:

只是实现这一目标的众多可能方法之一:

local userdata = { _array = { "A", "B", "C" } }
local mt = { }
local methods = { }

function mt.__index(userdata, k)
    if methods[k] then
        return methods[k]
    else
        return rawget(userdata, "_array")[k]
    end
end

function mt.__newindex(userdata, k, v)
    if methods[k] then
        error "can't assign to method!"
    else
        rawget(userdata, "_array")[k] = v
    end
end

function methods.count(userdata)
    return #rawget(userdata, "_array")
end

setmetatable(userdata, mt)

userdata[3] = "Z"

print(userdata[1])
print(userdata[2])
print(userdata[3])
print(userdata:count())

userdata.count = 0

编辑:正如 lhf 在他的评论中指出的那样,使用 metatable 并不危险,因为它是 __index 表,因为 c-methods 应该始终检查它们操作的 self 。

【讨论】:

  • 使用元表作为__index 本身并不危险。我一直都这样做。您只需要在元方法中小心一点,以确保您获得正确类型的用户数据。但无论如何你都必须这样做,因为除非你保护元表,否则总是可以调用getmetatable(u).__gc(u)
  • 哦,很高兴认识您,德菲格雷多先生!我完全忘记了 luaL_checkudata() 可以保护我们免受此类错误的影响。我会相应地编辑我的答案。谢谢你这个伟大的项目,先生!
猜你喜欢
  • 1970-01-01
  • 2013-12-07
  • 2013-06-06
  • 1970-01-01
  • 2012-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-21
相关资源
最近更新 更多