using UnityEngine; 
 | 
using System.Collections; 
 | 
using XLua; 
 | 
  
 | 
[GCOptimize(OptimizeFlag.PackAsTable)] 
 | 
public struct PushAsTableStruct 
 | 
{ 
 | 
    public int x; 
 | 
    public int y; 
 | 
} 
 | 
  
 | 
public class ReImplementInLua : MonoBehaviour { 
 | 
  
 | 
    // Use this for initialization 
 | 
    void Start () { 
 | 
        LuaEnv luaenv = new LuaEnv(); 
 | 
        //这两个例子都必须生成代码才能正常运行 
 | 
        //例子1:改造Vector3 
 | 
        //沿用Vector3原来的映射方案Vector3 -> userdata,但是把Vector3的方法实现改为lua实现,通过xlua.genaccessor实现不经过C#直接操作内存 
 | 
        //改为不经过C#的好处是性能更高,而且你可以省掉相应的生成代码以达成省text段的效果 
 | 
        //仍然沿用映射方案的好处是userdata比table更省内存,但操作字段比table性能稍低,当然,你也可以结合例子2的思路,把Vector3也改为映射到table 
 | 
        luaenv.DoString(@" 
 | 
            function test_vector3(title, v1, v2) 
 | 
               print(title) 
 | 
               print(v1.x, v1.y, v1.z) 
 | 
               print(v1, v2) 
 | 
               print(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 
 | 
            test_vector3('----before change metatable----', CS.UnityEngine.Vector3(1, 2, 3), CS.UnityEngine.Vector3(7, 8, 9)) 
 | 
  
 | 
            local get_x, set_x = xlua.genaccessor(0, 8) 
 | 
            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) 
 | 
                    set_x(o, x) 
 | 
                    set_y(o, y) 
 | 
                    set_z(o, z) 
 | 
                end 
 | 
            } 
 | 
  
 | 
            local mt = { 
 | 
                __index = function(o, k) 
 | 
                    --print('__index', k) 
 | 
                    if ins_methods[k] then return ins_methods[k] end 
 | 
                    return fields_getters[k] and fields_getters[k](o) 
 | 
                end, 
 | 
  
 | 
                __newindex = function(o, k, v) 
 | 
                    return fields_setters[k] and fields_setters[k](o, v) or error('no such field ' .. k) 
 | 
                end, 
 | 
  
 | 
                __tostring = function(o) 
 | 
                    return string.format('vector3 { %f, %f, %f}', o.x, o.y, o.z) 
 | 
                end, 
 | 
  
 | 
                __add = function(a, b) 
 | 
                    return CS.UnityEngine.Vector3(a.x + b.x, a.y + b.y, a.z + b.z) 
 | 
                end 
 | 
            } 
 | 
  
 | 
            xlua.setmetatable(CS.UnityEngine.Vector3, mt) 
 | 
            test_vector3('----after change metatable----', CS.UnityEngine.Vector3(1, 2, 3), CS.UnityEngine.Vector3(7, 8, 9)) 
 | 
        "); 
 | 
  
 | 
        Debug.Log("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); 
 | 
  
 | 
        //例子2:struct映射到table改造 
 | 
        //PushAsTableStruct传送到lua侧将会是table,例子里头还为这个table添加了一个成员方法SwapXY,静态方法Print,打印格式化,以及构造函数 
 | 
        luaenv.DoString(@" 
 | 
            local mt = { 
 | 
                __index = { 
 | 
                    SwapXY = function(o) --成员函数 
 | 
                        o.x, o.y = o.y, o.x 
 | 
                    end 
 | 
                }, 
 | 
  
 | 
                __tostring = function(o) --打印格式化函数 
 | 
                    return string.format('struct { %d, %d}', o.x, o.y) 
 | 
                end, 
 | 
            } 
 | 
  
 | 
            xlua.setmetatable(CS.PushAsTableStruct, mt) 
 | 
             
 | 
            local PushAsTableStruct = { 
 | 
                Print = function(o) --静态函数 
 | 
                    print(o.x, o.y) 
 | 
                end 
 | 
            } 
 | 
  
 | 
            setmetatable(PushAsTableStruct, { 
 | 
                __call = function(_, x, y) --构造函数 
 | 
                    return setmetatable({x = x, y = y}, mt) 
 | 
                end 
 | 
            }) 
 | 
             
 | 
            xlua.setclass(CS, 'PushAsTableStruct', PushAsTableStruct) 
 | 
        "); 
 | 
  
 | 
        PushAsTableStruct test; 
 | 
        test.x = 100; 
 | 
        test.y = 200; 
 | 
        luaenv.Global.Set("from_cs", test); 
 | 
  
 | 
        luaenv.DoString(@" 
 | 
            print('--------------from csharp---------------------') 
 | 
            assert(type(from_cs) == 'table') 
 | 
            print(from_cs) 
 | 
            CS.PushAsTableStruct.Print(from_cs) 
 | 
            from_cs:SwapXY() 
 | 
            print(from_cs) 
 | 
  
 | 
            print('--------------from lua---------------------') 
 | 
            local from_lua = CS.PushAsTableStruct(4, 5) 
 | 
            assert(type(from_lua) == 'table') 
 | 
            print(from_lua) 
 | 
            CS.PushAsTableStruct.Print(from_lua) 
 | 
            from_lua:SwapXY() 
 | 
            print(from_lua) 
 | 
        "); 
 | 
  
 | 
        luaenv.Dispose(); 
 | 
    } 
 | 
     
 | 
    // Update is called once per frame 
 | 
    void Update () { 
 | 
     
 | 
    } 
 | 
} 
 |