xlua - lua中操作c#对象

1, c#对象映射为lua的userdata

a) 默认情况,c#对象都是映射为lua的userdata,数据存放在c#层,调用函数也是走c#层。

function LuaUseVector3(v1, v2)
    v1.x = 10
    print(type(v1), v1.x, v1.y, v1.z)
    print("v1:", v1, "v2:", v2)
    print("v1+v2:", v1 + v2)
    v1:Set(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z)
    print(v1)
    print(CS.UnityEngine.Vector3.Normalize(v1))
end

print("----before change metatable----")
LuaUseVector3(CS.UnityEngine.Vector3(1, 2, 3), CS.UnityEngine.Vector3(7, 8, 9))

 

b) 通过xlua.genaccessor在lua层直接操作c#层的数据

方法:把对c#层的函数替换为走lua层的函数

local get_x, set_x = xlua.genaccessor(0, 8) --0_offset, 8_float类型
local get_y, set_y = xlua.genaccessor(4, 8)
local get_z, set_z = xlua.genaccessor(8, 8)

local fields_getters = {
    x = get_x, y = get_y, z = get_z
}
local fields_setters = {
    x = set_x, y = set_y, z = set_z
}

local ins_methods = {
    Set = function(o, x, y, z)
        print("lua Vec3 Set")
        set_x(o, x)
        set_y(o, y)
        set_z(o, z)
    end
}

local mt = {
    __index = function(o, k)
        if ins_methods[k] then return ins_methods[k] end --调用Vector3的Set函数, 变成调用lua这边的Set
        return fields_getters[k] and fields_getters[k](o)
    end,

    __newindex = function(o, k, v)
        if fields_setters[k] then fields_setters[k](o, v) else error('no such field ' .. k) end
    end,

    __tostring = function(o)
        return string.format('vector3 { %f, %f, %f}', o.x, o.y, o.z)
    end,

    __add = function(a, b)
        print("lua Vec3 add")
        return CS.UnityEngine.Vector3(a.x + b.x, a.y + b.y, a.z + b.z)
    end
}

xlua.setmetatable(CS.UnityEngine.Vector3, mt) --对c#的调用, 映射为对metatable的调用
print("----after change metatable----")
LuaUseVector3(CS.UnityEngine.Vector3(1, 2, 3), CS.UnityEngine.Vector3(7, 8, 9))

 

 

2, c#对象映射为lua的table

local LuaVec3Obj = {}
LuaVec3Obj.__index = LuaVec3Obj

function LuaVec3Obj:__tostring()
    return string.format("struct { %d, %d}", self.x, self.y)
end

function LuaVec3Obj:SwapXY()
    self.x, self.y = self.y, self.x
end

xlua.setmetatable(CS.UnityEngine.Vector3, LuaVec3Obj) --对c#的调用, 映射为对metatable的调用

local LuaVec3Clazz = {}

LuaVec3Clazz.__call = function(_, x, y, z) --对应c#层new的调用
    print("LuaVec3: new Vector3")
    local obj = {x = x, y = y, z = z}
    setmetatable(obj, LuaVec3Obj)
    return obj
end
setmetatable(LuaVec3Clazz, LuaVec3Clazz)

function LuaVec3Clazz.Print(o) --对应c#层静态函数的调用
    print("LuaVec3: Print", type(o), o)
end

xlua.setclass(CS.UnityEngine, "Vector3", LuaVec3Clazz) --c#层new或静态函数的调用, 映射为lua层的调用


local vec3 = CS.UnityEngine.Vector3(1, 2, 3)
print(type(vec3), vec3)
CS.UnityEngine.Vector3.Print(vec3)
vec3:SwapXY()
print(vec3)

 

posted @ 2024-02-28 22:42  yanghui01  阅读(17)  评论(0编辑  收藏  举报