如何设置metatable从另一个metatable继承,同时将userdata更改为另一个类型?

时间:2011-07-07 04:29:17

标签: c++ inheritance struct lua lua-userdata

这是我想在C ++中使用Lua C API做的事情。

我正在尝试找出一种从基本userdata对象派生userdata的好方法。

我希望能够做到这一点:

local item = me:GetCurrentItem()
print(item:GetPos())

而不是:

local item = me:GetCurrentItem()
print(item:GetBaseObject():GetPos())

在这些示例中,我:GetCurrentItem()返回带有一些函数的userdata,但它缺少以下项:GetBaseObject()返回的基函数。

我在“孤岛危机”SDK中绑定Lua用于学习目的。 SDK提供了作为结构的基础实体的接口。 IItem结构(me:GetCurrentItem())是相同的。 由于这些是结构,我无法将它们转换为基础结构或调用其基本函数。我必须使用IEntity * GetEntity()函数。

我已经尝试在__index中查找自我指针,但它会导致局部变量“item”成为“实体”,这有点显而易见,但是我希望它在调用GetPos函数之后还原,这在某种程度上似乎是不合逻辑的。

有没有人能很好地解决这个问题?

1 个答案:

答案 0 :(得分:2)

显而易见的解决方案是定义一个项目:GetPos()函数执行重定向。

function Item:GetPos()
  return self:GetBaseObject():GetPos()
end

其中Item是项目的元表。

这与在metatable上进行更改一样有效,而且问题较少。

编辑:我也可以帮助你解决重复问题。

您可以实现以下两个功能:

function delegate(klass, methodName, memberName)
  klass[methodName] = function(self, ...)
    local member = self[memberName]
    if type(member) == 'function' then member = self[memberName](self) end
    return member[methodName](member, ...)
  end
end

然后像这样使用它:

delegate(Item, 'GetPos', 'GetBaseObject')

该单行与上面的Item:GetPos 3行定义相同。

如果您需要重复这一点,可以使用其他功能进一步优化:

function delegateMany(klass, methodNames, memberName)
  for _,methodName in ipairs(methodNames) do
    delegateMethod(klass, methodName, memberName)
  end
end

应该允许你这样做:

deletageMany(Item, {'GetPost', 'SetPos', 'GetColor', 'SetColor'}, 'GetBaseObject')

我还没有测试过任何这些功能,所以要小心bug。它们应该与“获得的属性”(self:GetSomething()以及简单访问self.something)一起使用。该代码假定您始终使用“:”来调用委派的方法,因此在需要时添加self