在 C 中使用 Lua API 覆盖内置类型的运算符
Override operator for built in types with Lua API in C
我已经在我的 C++ 代码中集成了 Lua 5.3,并且我添加了几个数学 classes,它们应该可以在两个环境之间互换。
例如,我有一个具有 C 功能的 vec2 Lua 元表 link 它到我的 C++ class for vec2d。
现在,我的 vec2 元表有一个 __mul 运算符,这样我就可以编写 Lua 代码,例如:
local vector = vec2.create(1, 1)
local scaledVector = vector * 5
print(tostring(scaledVector)) -- outputs 5, 5
但有时,我只想反过来写,我也希望它能工作:
local vector = vec.create(1, 1)
local scaledVector = 5 * vector -- error: Class metatable function __index called on something else than userdata
print(tostring(scaledVector)) -- I want 5, 5
我明白为什么它不起作用。
这在 Lua 中完全可行吗?如果是这样……怎么办? (我正在寻找 C/C++ 解决方案,而不是用 Lua 编写的某种结构)
如果乘法的左操作数没有设置 __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 元方法的第一个参数始终是向量对象。
我已经在我的 C++ 代码中集成了 Lua 5.3,并且我添加了几个数学 classes,它们应该可以在两个环境之间互换。
例如,我有一个具有 C 功能的 vec2 Lua 元表 link 它到我的 C++ class for vec2d。
现在,我的 vec2 元表有一个 __mul 运算符,这样我就可以编写 Lua 代码,例如:
local vector = vec2.create(1, 1)
local scaledVector = vector * 5
print(tostring(scaledVector)) -- outputs 5, 5
但有时,我只想反过来写,我也希望它能工作:
local vector = vec.create(1, 1)
local scaledVector = 5 * vector -- error: Class metatable function __index called on something else than userdata
print(tostring(scaledVector)) -- I want 5, 5
我明白为什么它不起作用。
这在 Lua 中完全可行吗?如果是这样……怎么办? (我正在寻找 C/C++ 解决方案,而不是用 Lua 编写的某种结构)
如果乘法的左操作数没有设置 __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 元方法的第一个参数始终是向量对象。