xlua学习4 值传递避免gc

定义方法

声明一些方法,结构体,接口,作为测试对象
对于只包含值类型的结构体我们可以加GCOptimize标签,让xlua生成代码,优化gc
不要忘记在xlua中生成代码

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

然后创建实例和一些测试数据

IntParam f1;//测试方法
Vector3Param f2;
CustomValueTypeParam f3;
EnumParam f4;
DecimalParam f5;
ArrayAccess farr;
IExchanger ie;
Action flua;
LuaFunction add;
#endregion
#region test data
[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 };

接下来定义几个方法供lua调用测试

[LuaCallCSharp]
public float FloatParamMethod(float p)
{
    return p;
}
[LuaCallCSharp]
public Vector3 Vector3ParamMethod(Vector3 p)
{
    return p;
}
[LuaCallCSharp]
public MyStruct StructParamMethod(MyStruct p)
{
    return p;
}
[LuaCallCSharp]
public MyEnum EnumParamMethod(MyEnum p)
{
    return p;
}
[LuaCallCSharp]
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[0], arr[1] = arr[1], arr[0];
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[0]);
	self.a1[0], self.a1[1] = self.a1[1], self.a1[0]; -- 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]//只包含值类型的结构体,可以打GCOptimize标签,并生成代码,优化gc
[LuaCallCSharp]//lua中使用C#,打标签生成代码做优化,否则会使用反射的方式访问,非常耗资源
               //测试结构体
public struct Pedding
{
    public byte c;
}
[GCOptimize]
[LuaCallCSharp]
//测试结构体
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
}
[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);
}
#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
    [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 };
    #endregion
    #region test lua call c#
    //lua中调用的测试方法
    [LuaCallCSharp]
    public float FloatParamMethod(float p)
    {
        return p;
    }
    [LuaCallCSharp]
    public Vector3 Vector3ParamMethod(Vector3 p)
    {
        return p;
    }
    [LuaCallCSharp]
    public MyStruct StructParamMethod(MyStruct p)
    {
        return p;
    }
    [LuaCallCSharp]
    public MyEnum EnumParamMethod(MyEnum p)
    {
        return p;
    }
    [LuaCallCSharp]
    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[0], arr[1] = arr[1], arr[0];
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[0]);
	self.a1[0], self.a1[1] = self.a1[1], self.a1[0]; -- field
end
--对应C#类中的IExchanger接口
exchanger = {
	exchange = function(self, arr)
		array_exchange(arr);
	end
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值