1

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

我试图找出一种使 userdata 从基本 userdata 对象派生的好方法。

我希望能够做到这一点:

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

代替:

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

在这些示例中,me:GetCurrentItem() 返回带有一些函数的 userdata,但它缺少 item:GetBaseObject() 返回的基本函数。

我在 Crysis Wars SDK 中绑定 Lua 用于学习目的。SDK 为作为结构的基本实体提供了一个接口。IItem 结构 (me:GetCurrentItem()) 是相同的。由于这些是结构,我不能将它们转换为基本结构或调用它的基本函数。我必须使用 IEntity *GetEntity() 函数。

我尝试在 __index 中更改 self 指针,但它会导致局部变量“item”变为“entity”,这有点明显,但我希望它在调用 GetPos 函数后恢复,这在某种程度上似乎不合逻辑。

有没有人有一个很好的解决这个问题?

4

1 回答 1

2

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

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

其中 Item 是项目的元表。

这与对元表进行更改一样有效,而且问题更少。

编辑:我也可以在重复性方面为您提供一些帮助。

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

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')

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

于 2011-07-07T07:39:29.350 回答