在C中使用Lua API覆盖内置类型的运算符

我已经在我的C++代码中集成了Lua 5.3,并添加了几个数学类,它们应该在两个环境之间可互换。

例如,我有一个vec2 Lua元表,其中包含将其链接到我的vec2d C++类的C功能。

现在,我的vec2元表具有__mul运算符,使我可以编写像这样的Lua代码:

local vector = vec2.create(1, 1)
local scaledVector = vector * 5
print(tostring(scaledVector)) -- 输出 5, 5

但有时,我只是希望以相反的方式编写它,我也希望这样做:

local vector = vec.create(1, 1)
local scaledVector = 5 * vector -- error: 在userdata之外调用了Class元表函数__index
print(tostring(scaledVector)) -- 我想要 5, 5

我理解为什么它不起作用。

这在Lua中是否有可能?如果有...怎么做? (我正在寻找C/C++解决方案,而不是Lua中编写的某种构造)

点赞
用户90511
用户90511

如果一个乘法的左操作数没有设置__mul元方法,Lua将检查右操作数是否有__mul元方法。因此,5 * vec应该和vec * 5一样有效:

function scale_vector(vec, alpha)
  local out = {}
  for i=1,#vec do
    out[i] = vec[i] * alpha
  end
  return out
end

function print_vector(vec)
  for i=1, #vec do
    if i > 1 then
      io.stdout:write("\t")
    end
    io.stdout:write(vec[i])
  end
  io.stdout:write("\n")
end

mt = {
  __mul = function(a, b)
    if type(b) == "number" then
      print("Case 1")
      return scale_vector(a, b)
    elseif type(a) == "number" then
      print("Case 2")
      return scale_vector(b, a)
    else
      error("Cannot scale by non-number factor")
    end
  end
}

vec = {1,2,3}
setmetatable(vec, mt)

print_vector( vec * 5 )
print_vector( 5 * vec )

运行此脚本会得到

Case 1
5       10      15
Case 2
5       10      15

你可能出错的部分是,在__mul元方法内部,你需要进行一些测试来确定你的向量是第一个参数还是第二个参数。我猜想你的代码目前假设__mul元方法的第一个参数始终是向量对象。

2016-12-05 18:22:22