在Lua中使用元表

我正在尝试在Lua脚本中实现对象表示法。 这是我通过C API成功完成的内容:

  • 我创建了一个新的全局表“Test”作为类,并在其中添加了一个字段“new”,指向一个用C编写的函数, 即我可以在Lua代码中执行这个代码:“local obj = Test.new()”(它调用函数“new”)

  • “new” C函数创建并返回一个新表,并将函数注册到表中作为字段(例如“add”、“count” ...) 即我可以执行这个功能:“obj:add(“迈克”)”和“obj:count()”(obj作为第一个参数使用“:”符号传递)

两个问题:

1)一切都按照预期运行,但我想知道的是:在我的情况下使用元表的好处是什么? 我发现到处都可以使用元表来帮助我实现所尝试的内容,但我不明白它们在哪里有用? 将字段添加到表中作为方法不正确吗? 如果将它们添加为我的表元表,元表如何帮助我?

2)实际上,我正在尝试在Lua中复制C ++的行为。 例如,当我在C ++中写入此内容:“Test \ * obj = new Test();” 我期望C ++和测试构造函数为我返回Test实例的指针。 这正是我想让Lua为我做的事情。

问题在于,在这种情况下,我使用一个表,作为“new”返回的表,但不是指针,因此我可以稍后使用Lua(使用其字段)调用方法,就像标准的C ++对象一样(使用operator ->)。

为了能够在C函数中检索我的类的实际指针,我在“new”返回的表中添加了一个字段“ptr”(轻量级用户值)。如果没有它,我只能在我的C函数中操纵Lua表,仅此而已(因此无法在实际指针上调用更多方法)。

我的第二个问题是,这是正确的方法吗? 你有更好的想法,在没有这个“ptr”字段的情况下如何能够在任何地方操纵我的指针?

谢谢,尼古拉斯。

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

点赞
stackoverflow用户734069
stackoverflow用户734069

在我的情况下使用元表的优势是什么?

有以下几个优势:

Test.new = function() end

我刚刚破坏了你创建全局 Test 对象的能力。如果你使用元表来保护 Test 对象,我就要花费更多的精力才能做到。

另外:

local myTest = Test()

如果没有元表的话,你不能这样做(重载 __call 元方法)。使用元表比调用 Test.new 更符合 Lua 语法。

还有:

local testAdd = Test() + Test()

运算符重载。如果没有元表,你不可能做到这一点。

另外:

这正是我希望 Lua 为我做的。

这里有个建议:不要这样做。

不同的语言有不同的用途。你应该按照 Lua 的方式处理事情,而不是按照 C++ 的方式。我可以理解希望提供某些 C++ 机制(例如重载等)的想法,但你不应该只是因为 C++ 使用 new 就使用它。

此外,有很多库可以帮助你完成这项工作。SWIGLuabind 就是其中两个大型的库。

2011-11-17 23:45:12
stackoverflow用户282536
stackoverflow用户282536

主要原因是你能够得到__index元方法。如果没有它,每个实例对象都必须拥有与其相关联的所有函数:这会使表变得很大,并且使用大量内存。

local methods = {
    foo = function() return "foo" end ;
    bar = function() return "bar" end ;
    bob = function() return "bob" end ;
    hen = function() return "hen" end ;
}

因此,你可以选择

function new_no_mt()
    local t = {}
    for k, v in pairs (methods) do 
        t[k] = v 
    end
    return t
end

或者

local mt = { __index = methods }
function new_mt ()
    return setmetatable ({} , mt)
end

还有其他好处;

  • 定义运算符;
  • 通过比较元表进行简单的类型比较。
  • 在元表中更改方法会更改所有对象的方法,但仅更改一个对象的方法只更改该对象的方法。

否则,你所要做的听起来就像是userdata的完美应用场合。当你有__index元方法时userdata才能被索引(没有表来放置方法)。

2011-11-18 07:34:30