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]