2

我在 C# 中使用 LuaInterface,并“导出”了一些自定义 C# 类以在 Lua 中使用。例如:

local myVector = Vector2(10, 100)

但是,当我想使用本例中的类运算符时:

local v1 = Vector2(1, 1)
local v2 = Vector2(2, 2)
local v3 = v1 + v2

我收到以下错误:尝试对本地“p1”(用户数据值)执行算术运算

该类的 C# 变体确实具有 + 运算符:

    public static cVector2 operator +(cVector2 vector1, cVector2 vector2)
    {
        return new cVector2(vector1.X + vector2.X, vector1.Y + vector2.Y);
    }

我知道您应该使用 Lua 元表并为 * 运算符添加一个函数到“__mul”。但是 LuaInterface 不是自动完成的吗?如果没有,我怎么能自己自动化呢?

4

1 回答 1

2

But doesn't LuaInterface does that automatically?

No. You can see for yourself via:

for k,v in pairs(getmetatable(v1)) do
    print(k,v)
end

You'll see no __add metamethod.

if not, how could I automate this myself?

You'd have to modify the LuaInterface source to look for the operator+ method and add the __add metamethod. It simply doesn't do that now.

Given that you have the type proxy available (because you imported the type via import_type), you can access operator+, which is a static method on the type.

local v3 = Vector2.op_Addition(v1,v2)

To say v1 + v2 you'd need to modify the metamethod used by Vector2 object instance, but this requires creating an instance of the type:

local v1 = Vector2(1,1)
getmetatable(v1).__add = function(a,b) return Vector2.op_Addition(a,b) end

This affects the metamethod used by all instance, so you only need to do it once. Now you can write:

local v2 = Vector2(2,2)
local v3 = v1 + v2

Because you need an object to edit its metamethod, it would be hard to make this cleaner. If you modify your C# code to make sure that your class has a default constructor (i.e. no parameters), you could create a wrapper for import_type that does this:

function luanet.import_type_ex(typename)
    local T = luanet.import_type(typename)
    local mt = getmetatable(T())
    local function gethandler(name) return T[name] end
    local function addmethod(metamethodName, handlerName)
        local foundHandler, handler = pcall(gethandler, handlerName)
        if foundHandler then mt[metamethodName] = handler end
    end
    addmethod('__add', 'op_Addition')
    addmethod('__sub', 'op_Subtraction')
    addmethod('__mul', 'op_Multiply')
    addmethod('__div', 'op_Division')
    return T
end

You could extend that for other operators. Note that LuaInterface throws an exception if you try to access a member that doesn't exist (rather than returning nil), so we have to wrap the attempt to access a handler with pcall.

With that in place you could write:

Vector2 = luanet.import_type_ex('YourNamespace.Vector2')
local v1 = Vector2(10)
local v2 = Vector2(20)
local v3 = v1 + v2

Of course, this would work for other types that have overloaded operators.

LuaInterface is a bit of a hot mess. There are a few projects in the Lua world like it, where somebody at PUC-Rio does it as a research project, publishes a paper, then abandons it. They did it to see if they could, not because they actually use it.

于 2014-04-08T21:30:01.897 回答