mypro334 发表于 2021-8-11 20:33

xlua学习4 值传递避免gc

定义方法

声明一些方法,结构体,接口,作为测试对象
对于只包含值类型的结构体我们可以加GCOptimize标签,让xlua生成代码,优化gc
不要忘记在xlua中生成代码
//只包含值类型的结构体,可以打GCOptimize标签,并生成代码,优化gc
//lua中使用C#,打标签生成代码做优化,否则会使用反射的方式访问,非常耗资源
               //测试结构体
public struct Pedding
{
    public byte 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;
}

//测试枚举
public enum MyEnum
{
    E1,
    E2
}

public delegate int IntParam(int p);//测试方法

public delegate Vector3 Vector3Param(Vector3 p);//测试方法

public delegate MyStruct CustomValueTypeParam(MyStruct p);//测试方法

public delegate MyEnum EnumParam(MyEnum p);//测试方法

public delegate decimal DecimalParam(decimal p);//测试方法

public delegate void ArrayAccess(Array arr);//测试方法

//测试接口
public interface IExchanger
{
    void exchange(Array arr);
}然后创建实例和一些测试数据
IntParam f1;//测试方法
Vector3Param f2;
CustomValueTypeParam f3;
EnumParam f4;
DecimalParam f5;
ArrayAccess farr;
IExchanger ie;
Action flua;
LuaFunction add;
#endregion
#region test data

public double[] a1 = new double[] { 1, 2 };//测试数据

public Vector3[] a2 = new Vector3[] { new Vector3(1, 2, 3), new Vector3(4, 5, 6) };

public MyStruct[] a3 = new MyStruct[] { new MyStruct(1, 2), new MyStruct(3, 4) };

public MyEnum[] a4 = new MyEnum[] { MyEnum.E1, MyEnum.E2 };

public decimal[] a5 = new decimal[] { 1.00001M, 2.00002M };接下来定义几个方法供lua调用测试

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;
}编写lua测试代码

在lua中根据刚刚定义的数据结构,生成表和方法
A = { B = { C = 789}};--定义一个结构体
GDATA = 1234;--定义一个num类型
local v3 = CS.UnityEngine.Vector3(7, 8, 9);--调用c#类中的参数
local vt = CS.MyStruct(5, 6);--调用c#类中的参数
--相当于泛型
function id(...)
        return ...;
end
--简单的相加方法
function add(a, b)
        return a + b ;
end
--数组index0 和 index1的交换
function array_exchange(arr)
        arr, arr = arr, arr;
end
--测试访问C#中的方法
function lua_access_csharp()
        self:FloatParamMethod(123); --primitive
        self:Vector3ParamMethod(v3); --vector3
        local rnd = math.random(1, 100);
        local r = self:Vector3ParamMethod({x = 1, y = 2, z = rnd}); --vector3
        assert(r.x == 1 and r.y == 2 and r.z == rnd);
        self:StructParamMethod(vt); --custom struct
        r = self:StructParamMethod({a = 1, b = rnd, e = {c = rnd}});
        assert(r.b == rnd and r.e.c == rnd);
        self:EnumParamMethod(CS.MyEnum.E2); --enum
        self:DecimalParamMethod(self.a5);
        self.a1, self.a1 = self.a1, self.a1; -- field
end
--对应C#类中的IExchanger接口
exchanger = {
        exchange = function(self, arr)
                array_exchange(arr);
        end
};
获取lua中的方法

scriptEnv = LuaEnvExtension.Instance.NewTable();//在主lua环境中创建一个新的表作为当前脚本的环境
LuaTable meta = LuaEnvExtension.Instance.NewTable();//创建一个新的表格存全局变量
meta.Set("__index", LuaEnvExtension.Instance.Global);//获取全局变量作为元方法
scriptEnv.SetMetaTable(meta);//设置meta为当前脚本的元表
meta.Dispose();//回收meta
LuaEnvExtension.Instance.DoString(luaText.text, "NoGCTest", scriptEnv);//拷贝lua脚本的方法到scriptEnv中
scriptEnv.Set("self", this);//设置自身
scriptEnv.Get("id", out f1);//获取泛型测试方法,我们并没有传给id方法参数,所以f1-f5都是空的
scriptEnv.Get("id", out f2);
scriptEnv.Get("id", out f3);
scriptEnv.Get("id", out f4);
scriptEnv.Get("id", out f5);
scriptEnv.Get("array_exchange", out farr);//获取lua中的方法
scriptEnv.Get("lua_access_csharp", out flua);
scriptEnv.Get("exchanger", out ie);
scriptEnv.Get("add", out add);
scriptEnv.Set("g_int", 123);
scriptEnv.Set(123, 456);
int i;
scriptEnv.Get("g_int", out i);
scriptEnv.Get(123, out i);调用测试方法

private void Update()
{
    //测试f1-f5方法
    f1(1);
    f2(new Vector3(1, 2, 3));
    MyStruct mystruct1 = new MyStruct(5, 6);
    f3(mystruct1);
    f4(MyEnum.E1);
    decimal dec1 = -32132143143100109.00010001010M;
    f5(dec1);
    add.Func<int, int, int>(34, 56); // LuaFunction.Func<T1, T2, TResult>是个方便调用的类型,可以自定义其他方法快捷调用
                                     //测试a1-a5数据
    farr(a1); //primitive value type array
    farr(a2); //vector3 array
    farr(a3); //custom struct array
    farr(a4); //enum arry
    farr(a5); //decimal arry
    flua();//调用lua中的lua_access_csharp方法测试C#中的数据
    ie.exchange(a2);//接口测试
    scriptEnv.Set("g_int", 456);//调用lua数据测试
    int i;
    scriptEnv.Get("g_int", out i);
    scriptEnv.Set(123.0001, mystruct1);
    MyStruct mystruct2;
    scriptEnv.Get(123.0001, out mystruct2);
    decimal dec2 = 0.0000001M;
    scriptEnv.Set((byte)12, dec1);
    scriptEnv.Get((byte)12, out dec2);
    int gdata = scriptEnv.Get<int>("GDATA");
    scriptEnv.SetInPath("GDATA", gdata + 1);
    int abc = scriptEnv.GetInPath<int>("A.B.C");
    scriptEnv.SetInPath("A.B.C", abc + 1);
    //检测是否满足gc回收条件
    if (Time.time - LuaEnvExtension.lastGCTime > gcInterval)
    {
      LuaEnvExtension.Instance.GC();
      LuaEnvExtension.lastGCTime = Time.time;
    }
}回收内存

private void OnDestroy()
{
    //回收内存
    f1 = null;
    f2 = null;
    f3 = null;
    f4 = null;
    f5 = null;
    a1 = null;
    a2 = null;
    a3 = null;
    a4 = null;
    a5 = null;
    farr = null;
    flua = null;
    ie = null;
    add = null;
    scriptEnv.Dispose();
}完整代码

C#部分的代码
using System;
using UnityEngine;
using XLua;

#region test struct and method
//只包含值类型的结构体,可以打GCOptimize标签,并生成代码,优化gc
//lua中使用C#,打标签生成代码做优化,否则会使用反射的方式访问,非常耗资源
               //测试结构体
public struct Pedding
{
    public byte 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;
}

//测试枚举
public enum MyEnum
{
    E1,
    E2
}

public delegate int IntParam(int p);//测试方法

public delegate Vector3 Vector3Param(Vector3 p);//测试方法

public delegate MyStruct CustomValueTypeParam(MyStruct p);//测试方法

public delegate MyEnum EnumParam(MyEnum p);//测试方法

public delegate decimal DecimalParam(decimal p);//测试方法

public delegate void ArrayAccess(Array arr);//测试方法

//测试接口
public interface IExchanger
{
    void exchange(Array arr);
}
#endregion
public class NoGCTest : MonoBehaviour
{
    private const float gcInterval = 1f;//gc回收间隔 1秒
    public TextAsset luaText;//lua脚本
    private LuaTable scriptEnv;//脚本的lua环境
    #region test method params
    IntParam f1;//测试方法
    Vector3Param f2;
    CustomValueTypeParam f3;
    EnumParam f4;
    DecimalParam f5;
    ArrayAccess farr;
    IExchanger ie;
    Action flua;
    LuaFunction add;
    #endregion
    #region test data
   
    public double[] a1 = new double[] { 1, 2 };//测试数据
   
    public Vector3[] a2 = new Vector3[] { new Vector3(1, 2, 3), new Vector3(4, 5, 6) };
   
    public MyStruct[] a3 = new MyStruct[] { new MyStruct(1, 2), new MyStruct(3, 4) };
   
    public MyEnum[] a4 = new MyEnum[] { MyEnum.E1, MyEnum.E2 };
   
    public decimal[] a5 = new decimal[] { 1.00001M, 2.00002M };
    #endregion
    #region test lua call c#
    //lua中调用的测试方法
   
    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;
    }
    #endregion
    private void Awake()
    {
      scriptEnv = LuaEnvExtension.Instance.NewTable();//在主lua环境中创建一个新的表作为当前脚本的环境
      LuaTable meta = LuaEnvExtension.Instance.NewTable();//创建一个新的表格存全局变量
      meta.Set("__index", LuaEnvExtension.Instance.Global);//获取全局变量作为元方法
      scriptEnv.SetMetaTable(meta);//设置meta为当前脚本的元表
      meta.Dispose();//回收meta
      LuaEnvExtension.Instance.DoString(luaText.text, "NoGCTest", scriptEnv);//拷贝lua脚本的方法到scriptEnv中
      scriptEnv.Set("self", this);//设置自身
      scriptEnv.Get("id", out f1);//获取泛型测试方法,我们并没有传给id方法参数,所以f1-f5都是空的
      scriptEnv.Get("id", out f2);
      scriptEnv.Get("id", out f3);
      scriptEnv.Get("id", out f4);
      scriptEnv.Get("id", out f5);
      scriptEnv.Get("array_exchange", out farr);//获取lua中的方法
      scriptEnv.Get("lua_access_csharp", out flua);
      scriptEnv.Get("exchanger", out ie);
      scriptEnv.Get("add", out add);
      scriptEnv.Set("g_int", 123);
      scriptEnv.Set(123, 456);
      int i;
      scriptEnv.Get("g_int", out i);
      Debug.Log("g_int:" + i);
      scriptEnv.Get(123, out i);
      Debug.Log("123:" + i);
    }
    private void Update()
    {
      //测试f1-f5方法
      f1(1);
      f2(new Vector3(1, 2, 3));
      MyStruct mystruct1 = new MyStruct(5, 6);
      f3(mystruct1);
      f4(MyEnum.E1);
      decimal dec1 = -32132143143100109.00010001010M;
      f5(dec1);
      add.Func<int, int, int>(34, 56); // LuaFunction.Func<T1, T2, TResult>是个方便调用的类型,可以自定义其他方法快捷调用
      //测试a1-a5数据
      farr(a1); //primitive value type array
      farr(a2); //vector3 array
      farr(a3); //custom struct array
      farr(a4); //enum arry
      farr(a5); //decimal arry
      flua();//调用lua中的lua_access_csharp方法测试C#中的数据
      ie.exchange(a2);//接口测试
      scriptEnv.Set("g_int", 456);//调用lua数据测试
      int i;
      scriptEnv.Get("g_int", out i);
      scriptEnv.Set(123.0001, mystruct1);
      MyStruct mystruct2;
      scriptEnv.Get(123.0001, out mystruct2);
      decimal dec2 = 0.0000001M;
      scriptEnv.Set((byte)12, dec1);
      scriptEnv.Get((byte)12, out dec2);
      int gdata = scriptEnv.Get<int>("GDATA");
      scriptEnv.SetInPath("GDATA", gdata + 1);
      int abc = scriptEnv.GetInPath<int>("A.B.C");
      scriptEnv.SetInPath("A.B.C", abc + 1);
      //检测是否满足gc回收条件
      if (Time.time - LuaEnvExtension.lastGCTime > gcInterval)
      {
            LuaEnvExtension.Instance.GC();
            LuaEnvExtension.lastGCTime = Time.time;
      }
    }
    private void OnDestroy()
    {
      //回收内存
      f1 = null;
      f2 = null;
      f3 = null;
      f4 = null;
      f5 = null;
      a1 = null;
      a2 = null;
      a3 = null;
      a4 = null;
      a5 = null;
      farr = null;
      flua = null;
      ie = null;
      add = null;
      scriptEnv.Dispose();
    }
}lua部分的代码
A = { B = { C = 789}};--定义一个结构体
GDATA = 1234;--定义一个num类型
local v3 = CS.UnityEngine.Vector3(7, 8, 9);--调用c#类中的参数
local vt = CS.MyStruct(5, 6);--调用c#类中的参数
--相当于泛型
function id(...)
        return ...;
end
--简单的相加方法
function add(a, b)
        return a + b ;
end
--数组index0 和 index1的交换
function array_exchange(arr)
        arr, arr = arr, arr;
end
--测试访问C#中的方法
function lua_access_csharp()
        self:FloatParamMethod(123); --primitive
        self:Vector3ParamMethod(v3); --vector3
        local rnd = math.random(1, 100);
        local r = self:Vector3ParamMethod({x = 1, y = 2, z = rnd}); --vector3
        assert(r.x == 1 and r.y == 2 and r.z == rnd);
        self:StructParamMethod(vt); --custom struct
        r = self:StructParamMethod({a = 1, b = rnd, e = {c = rnd}});
        assert(r.b == rnd and r.e.c == rnd);
        self:EnumParamMethod(CS.MyEnum.E2); --enum
        self:DecimalParamMethod(self.a5);
        self.a1, self.a1 = self.a1, self.a1; -- field
end
--对应C#类中的IExchanger接口
exchanger = {
        exchange = function(self, arr)
                array_exchange(arr);
        end
};
页: [1]
查看完整版本: xlua学习4 值传递避免gc