xlua入门(4)c#和Lua之间值类型的传递避免GC


  • 避免值类型的GC

一个C#纯值类型(注:指的是一个只包含值类型的struct,可以嵌套其它只包含值类型的struct)或者C#枚举值加上了这个配置。xLua会为该类型生成gc优化代码,效果是该值类型在lua和c#间传递不产生(C#)gc alloc,该类型的数组访问也不产生gc
除枚举之外,包含无参构造函数的复杂类型,都会生成lua table到该类型,以及改类型的一维数组的转换代码,这将会优化这个转换的性能,包括更少的gc alloc。
using UnityEngine;
using System;
using XLua;

namespace XLuaTest
{
    //一个C#纯值类型(注:指的是一个只包含值类型的struct,可以嵌套其它只包含值类型的struct)或者C#枚举值加上了这个配置。
    //xLua会为该类型生成gc优化代码,效果是该值类型在lua和c#间传递不产生(C#)gc alloc,该类型的数组访问也不产生gc
    [GCOptimize]
    [LuaCallCSharp]
    public struct Pedding
    {
        public byte c;
    }

    [GCOptimize]
    [LuaCallCSharp]     //lua调用c#
    public struct MyStruct
    {
        public MyStruct(int p1, int p2)
        {
            a = p1;
            b = p2;
            c = p2;
            e.c = (byte)p1;
        }
        public int a;
        public int b;
        public decimal c;
        public Pedding e;
    }

    [LuaCallCSharp]
    public enum MyEnum
    {
        E1,
        E2
    }

    ///c#调用lua
    [CSharpCallLua]
    public delegate int IntParam(int p);

    [CSharpCallLua]
    public delegate Vector3 Vector3Param(Vector3 p);

    [CSharpCallLua]
    public delegate MyStruct CustomValueTypeParam(MyStruct p);

    [CSharpCallLua]
    public delegate MyEnum EnumParam(MyEnum p);

    [CSharpCallLua]
    public delegate decimal DecimalParam(decimal p);

    [CSharpCallLua]
    public delegate void ArrayAccess(Array arr);

    [CSharpCallLua]
    public interface IExchanger
    {
        void exchange(Array arr);
    }

    [LuaCallCSharp]
    public class NoGc : MonoBehaviour
    {
        //lua虚拟机,建议全局唯一
        LuaEnv luaenv = new LuaEnv();

        //委托用来调用lua方法
        IntParam f1;
        Vector3Param f2;
        CustomValueTypeParam f3;
        EnumParam f4;
        DecimalParam f5;
        ArrayAccess farr;

        Action flua;

        //接口用来映射lua里的table
        IExchanger ie;

        //映射lua方法 LuaFunction上有个变参的Call函数,可以传任意类型,任意个数的参数,返回值是object的数组,对应于lua的多返回
        LuaFunction add;

        [NonSerialized]
        public double[] a1 = new double[] { 1, 2 };
        [NonSerialized]
        public Vector3[] a2 = new Vector3[] { new Vector3(1, 2, 3), new Vector3(4, 5, 6) };
        [NonSerialized]
        public MyStruct[] a3 = new MyStruct[] { new MyStruct(1, 2), new MyStruct(3, 4) };
        [NonSerialized]
        public MyEnum[] a4 = new MyEnum[] { MyEnum.E1, MyEnum.E2 };
        [NonSerialized]
        public decimal[] a5 = new decimal[] { 1.00001M, 2.00002M };

        public float FloatParamMethod(float p)
        {
            return p;
        }

        public Vector3 Vector3ParamMethod(Vector3 p)
        {
            return p;
        }

        public MyStruct StructParamMethod(MyStruct p)
        {
            return p;
        }

        public MyEnum EnumParamMethod(MyEnum p)
        {
            return p;
        }

        public decimal DecimalParamMethod(decimal p)
        {
            return p;
        }

        // Use this for initialization
        void Start()
        {
            luaenv.DoString(@"
                function id(...)
                    return ...
                end

                function add(a, b) return a + b end

                function array_exchange(arr)
                    arr[0], arr[1] = arr[1], arr[0]
                end

                --获取一个vector3对象
                local v3 = CS.UnityEngine.Vector3(7, 8, 9)

                --获取XLuaTest空间下的MyStruct结构体
                local vt = CS.XLuaTest.MyStruct(5, 6)

                --访问c#,加了[LuaCallCSharp]特性
                function lua_access_csharp()
                    monoBehaviour:FloatParamMethod(123) --primitive
                    monoBehaviour:Vector3ParamMethod(v3) --vector3
                    local rnd = math.random(1, 100)
                    local r = monoBehaviour:Vector3ParamMethod({x = 1, y = 2, z = rnd}) --vector3
                    assert(r.x == 1 and r.y == 2 and r.z == rnd)
                    monoBehaviour:StructParamMethod(vt) --custom struct
                    r = monoBehaviour:StructParamMethod({a = 1, b = rnd, e = {c = rnd}})
                    assert(r.b == rnd and r.e.c == rnd)
                    monoBehaviour:EnumParamMethod(CS.XLuaTest.MyEnum.E2) --enum
                    monoBehaviour:DecimalParamMethod(monoBehaviour.a5[0])
                    monoBehaviour.a1[0], monoBehaviour.a1[1] = monoBehaviour.a1[1], monoBehaviour.a1[0] -- field
                end

                exchanger = {
                    exchange = function(self, arr)
                        array_exchange(arr)
                    end
                }

                A = { B = { C = 789}}
                GDATA = 1234;
            ");

            //设置当前对象给lua脚本
            luaenv.Global.Set("monoBehaviour", this);

            //获取lua中的全局方法映射到delegate中
            luaenv.Global.Get("id", out f1);
            //f1 = luaenv.Global.Get<IntParam>("id");
            luaenv.Global.Get("id", out f2);
           // f2 = luaenv.Global.Get<Vector3Param>("id");
            luaenv.Global.Get("id", out f3);
           // f3 = luaenv.Global.Get<CustomValueTypeParam>("id");
            luaenv.Global.Get("id", out f4);
           // f4 = luaenv.Global.Get<EnumParam>("id");
            luaenv.Global.Get("id", out f5);
            //f5 = luaenv.Global.Get<DecimalParam>("id");
            luaenv.Global.Get("array_exchange", out farr);
            //farr = luaenv.Global.Get<ArrayAccess>("array_exchange");
            luaenv.Global.Get("lua_access_csharp", out flua);
            //flua = luaenv.Global.Get<Action>("lua_access_csharp");
            luaenv.Global.Get("add", out add);
            //add = luaenv.Global.Get<LuaFunction>("add");

            //映射table到接口
            luaenv.Global.Get("exchanger", out ie);
            //ie = luaenv.Global.Get<IExchanger>("exchanger");


            luaenv.Global.Set("g_int", 123);
            luaenv.Global.Set(123, 456);
            int i;
            luaenv.Global.Get("g_int", out i);
            Debug.Log("g_int:" + i);
            luaenv.Global.Get(123, out i);
            Debug.Log("123:" + i);
        }


        //值类型之间为产生GC
        void Update()
        {
            // c# call lua function with value type but no gc (using delegate)
            f1(1); // primitive type
            Vector3 v3 = new Vector3(1, 2, 3); // vector3
            f2(v3);
            MyStruct mystruct = new MyStruct(5, 6); // custom complex value type
            f3(mystruct);
            f4(MyEnum.E1); //enum 
            decimal d = -32132143143100109.00010001010M;
            decimal dr = f5(d);
            System.Diagnostics.Debug.Assert(d == dr);

            // using LuaFunction.Func<T1, T2, TResult>
            System.Diagnostics.Debug.Assert(add.Func<int, int, int>(34, 56) == (34 + 56)); // LuaFunction.Func<T1, T2, TResult>

            // lua access c# value type array no gc
            farr(a1); //primitive value type array
            farr(a2); //vector3 array
            farr(a3); //custom struct array
            farr(a4); //enum arry
            farr(a5); //decimal arry

            // lua call c# no gc with value type
            flua();

            //c# call lua using interface
            ie.exchange(a2);

            //no gc LuaTable use
            luaenv.Global.Set("g_int", 456);
            int i;
            luaenv.Global.Get("g_int", out i);
            System.Diagnostics.Debug.Assert(i == 456);

            luaenv.Global.Set(123.0001, mystruct);
            MyStruct mystruct2;
            luaenv.Global.Get(123.0001, out mystruct2);
            System.Diagnostics.Debug.Assert(mystruct2.b == mystruct.b);

            decimal dr2 = 0.0000001M;
            luaenv.Global.Set((byte)12, d);
            luaenv.Global.Get((byte)12, out dr2);
            System.Diagnostics.Debug.Assert(d == dr2);

            int gdata = luaenv.Global.Get<int>("GDATA");
            luaenv.Global.SetInPath("GDATA", gdata + 1);
            //gdata = luaenv.Global.Get<int>("GDATA");
            //Debug.Log(gdata);
            System.Diagnostics.Debug.Assert(luaenv.Global.Get<int>("GDATA") == gdata + 1);

            int abc = luaenv.Global.GetInPath<int>("A.B.C");  //789
            luaenv.Global.SetInPath("A.B.C", abc + 1);
            //Debug.Log(luaenv.Global.GetInPath<int>("A.B.C"));
            System.Diagnostics.Debug.Assert(luaenv.Global.GetInPath<int>("A.B.C") == abc + 1);

            //清除Lua的未手动释放的LuaBase(比如,LuaTable, LuaFunction),以及其它一些事情。
            luaenv.Tick();
        }

        void OnDestroy()
        {
            f1 =  null;
            f2 = null;
            f3 = null;
            f4 = null;
            f5 = null;
            farr = null;
            flua = null;
            ie = null;
            add = null;
            luaenv.Dispose();
        }
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值