////////////////////////// CSharpCallLua /////////////////////////////////////////////
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using XLua;
using System;
namespace Tutorial
{
public class CSCallLua : MonoBehaviour
{
LuaEnv luaenv = null;
string script = @"
a = 1
b = 'hello world'
c = true
d = {
f1 = 12, f2 = 34,
1, 2, 3,
add = function(self, a, b)
print('d.add called')
return a + b
end
}
function e()
print('i am e')
end
function f(a, b)
print('a', a, 'b', b)
return 1, {f1 = 1024}
end
function ret_e()
print('ret_e called')
return e
end
";
public class DClass
{
public int f1;
public int f2;
public int f3; // My Add
}
[CSharpCallLua]
public interface ItfD
{
int f1 { get; set; }
int f2 { get; set; }
int add(int a, int b);
}
[CSharpCallLua]
public delegate int FDelegate(int a, string b, out DClass c);
[CSharpCallLua]
public delegate Action GetE();
// Use this for initialization
void Start()
{
luaenv = new LuaEnv();
luaenv.DoString(script);
Debug.Log("_G.a = " + luaenv.Global.Get<int>("a"));
Debug.Log("_G.b = " + luaenv.Global.Get<string>("b"));
Debug.Log("_G.c = " + luaenv.Global.Get<bool>("c"));
// Log output---- _G.a = 1
// Log output---- _G.b = hello world
// Log output---- _G.c = True
DClass d = luaenv.Global.Get<DClass>("d");//映射到有對應字段的class,by value
//Debug.Log("_G.d = {f1=" + d.f1 + ", f2=" + d.f2 + "}");
Debug.Log("_G.d = {f1=" + d.f1 + ", f2=" + d.f2 + "}" + ", f3=" + d.f3); // My Add
// Log output---- _G.d = {f1=12, f2=34}, f3=0
Dictionary<string, double> d1 = luaenv.Global.Get<Dictionary<string, double>>("d");//映射到Dictionary<string, double>,by value
Debug.Log("_G.d = {f1=" + d1["f1"] + ", f2=" + d1["f2"] + "}, d.Count=" + d1.Count);
// Log output---- _G.d = {f1=12, f2=34}, d.Count=2
// ---- My Add ----
Dictionary<int, double> d1_Temp = luaenv.Global.Get<Dictionary<int, double>>("d");//映射到Dictionary<int, double>,by value
// ---- 表裏 還是按 1 開始
Debug.Log("- My Add --_G.d = {d1_Temp[1]=" + d1_Temp[1] + ", d1_Temp[2]=" + d1_Temp[2] + ", d1_Temp[3]=" + d1_Temp[3] + "}, d.Count=" + d1_Temp.Count); // My Add
// ---- My Add ----
// Log output---- - My Add --_G.d = {d1_Temp[1]=1, d1_Temp[2]=2, d1_Temp[3]=3}, d.Count=3
List<double> d2 = luaenv.Global.Get<List<double>>("d"); //映射到List<double>,by value
//Debug.Log("_G.d.len = " + d2.Count);
// ---- 這裏是 List 從 0 開始
Debug.Log("_G.d.len = " + d2.Count + ", d2[0]=" + d2[0] + ", d2[1]=" + d2[1] + ", d2[2]=" + d2[2]); // My Add
// Log output---- _G.d.len = 3, d2[0]=1, d2[1]=2, d2[2]=3
ItfD d3 = luaenv.Global.Get<ItfD>("d"); //映射到interface實例,by ref,這個要求interface加到生成列表,否則會返回null,建議用法
d3.f2 = 1000;
Debug.Log("_G.d = {f1=" + d3.f1 + ", f2=" + d3.f2 + "}");
Debug.Log("_G.d:add(1, 2)=" + d3.add(1, 2));
// Log output---- _G.d = {f1=12, f2=1000}
// Log output---- LUA: d.add called
// Log output---- _G.d:add(1, 2)=3
LuaTable d4 = luaenv.Global.Get<LuaTable>("d");//映射到LuaTable,by ref
//Debug.Log("_G.d = {f1=" + d4.Get<int>("f1") + ", f2=" + d4.Get<int>("f2") + "}");
// ---- 這裏是 LuaTable 從 1 開始
Debug.Log("_G.d = {f1=" + d4.Get<int>("f1") + ", f2=" + d4.Get<int>("f2") + "}" + " ,____" + d4.Get<int>(1)); // My Add
// Log output---- _G.d = {f1=12, f2=1000} ,____1
Action e = luaenv.Global.Get<Action>("e");//映射到一個delgate,要求delegate加到生成列表,否則返回null,建議用法
e();
// Log output---- LUA: i am e
FDelegate f = luaenv.Global.Get<FDelegate>("f");
DClass d_ret;
int f_ret = f(100, "John", out d_ret);//lua的多返回值映射:從左往右映射到c#的輸出參數,輸出參數包括返回值,out參數,ref參數
Debug.Log("ret.d = {f1=" + d_ret.f1 + ", f2=" + d_ret.f2 + "}, ret=" + f_ret);
// Log output---- LUA: a 100 b John
// Log output---- ret.d = {f1=1024, f2=0}, ret=1
GetE ret_e = luaenv.Global.Get<GetE>("ret_e");//delegate可以返回更復雜的類型,甚至是另外一個delegate
e = ret_e();
e();
// Log output---- LUA: ret_e called
// Log output---- LUA: i am e
LuaFunction d_e = luaenv.Global.Get<LuaFunction>("e");
d_e.Call();
// Log output---- LUA: i am e
}
// Update is called once per frame
void Update()
{
if (luaenv != null)
{
luaenv.Tick();
}
}
void OnDestroy()
{
luaenv.Dispose();
}
}
}
/////////////////////////////////////////////////////////////////////////
//////////////////////////////// LuaCallCSharp /////////////////////////////
using UnityEngine;
using System.Collections;
using System;
using XLua;
using System.Collections.Generic;
namespace Tutorial
{
[LuaCallCSharp]
public class BaseClass
{
public static void BSFunc()
{
Debug.Log("Derived Static Func, BSF = " + BSF);
}
public static int BSF = 1;
public void BMFunc()
{
Debug.Log("Derived Member Func, BMF = " + BMF);
}
public int BMF { get; set; }
}
public struct Param1
{
public int x;
public string y;
}
[LuaCallCSharp]
public enum TestEnum
{
E1,
E2
}
[LuaCallCSharp]
public class DerivedClass : BaseClass
{
[LuaCallCSharp]
public enum TestEnumInner
{
E3,
E4
}
public void DMFunc()
{
Debug.Log("Derived Member Func, DMF = " + DMF);
}
public int DMF { get; set; }
public double ComplexFunc(Param1 p1, ref int p2, out string p3, Action luafunc, out Action csfunc)
{
Debug.Log("P1 = {x=" + p1.x + ",y=" + p1.y + "},p2 = " + p2);
luafunc();
p2 = p2 * p1.x;
p3 = "hello " + p1.y;
csfunc = () =>
{
Debug.Log("csharp callback invoked!");
};
return 1.23;
}
public void TestFunc(int i)
{
Debug.Log("TestFunc(int i)");
}
public void TestFunc(string i)
{
Debug.Log("TestFunc(string i)");
}
public static DerivedClass operator +(DerivedClass a, DerivedClass b)
{
DerivedClass ret = new DerivedClass();
ret.DMF = a.DMF + b.DMF;
return ret;
}
public void DefaultValueFunc(int a = 100, string b = "cccc", string c = null)
{
UnityEngine.Debug.Log("DefaultValueFunc: a=" + a + ",b=" + b + ",c=" + c);
}
public void VariableParamsFunc(int a, params string[] strs)
{
UnityEngine.Debug.Log("VariableParamsFunc: a =" + a);
foreach (var str in strs)
{
UnityEngine.Debug.Log("str:" + str);
}
}
public TestEnum EnumTestFunc(TestEnum e)
{
Debug.Log("EnumTestFunc: e=" + e);
return TestEnum.E2;
}
public Action<string> TestDelegate = (param) =>
{
Debug.Log("TestDelegate in c#:" + param);
};
public event Action TestEvent;
public void CallEvent()
{
TestEvent();
}
public ulong TestLong(long n)
{
return (ulong)(n + 1);
}
class InnerCalc : ICalc
{
public int add(int a, int b)
{
return a + b;
}
public int id = 100;
}
public ICalc GetCalc()
{
return new InnerCalc();
}
public void GenericMethod<T>()
{
Debug.Log("GenericMethod<" + typeof(T) + ">");
}
}
[LuaCallCSharp]
public interface ICalc
{
int add(int a, int b);
}
[LuaCallCSharp]
public static class DerivedClassExtensions
{
public static int GetSomeData(this DerivedClass obj)
{
Debug.Log("GetSomeData ret = " + obj.DMF);
return obj.DMF;
}
public static int GetSomeBaseData(this BaseClass obj)
{
Debug.Log("GetSomeBaseData ret = " + obj.BMF);
return obj.BMF;
}
public static void GenericMethodOfString(this DerivedClass obj)
{
obj.GenericMethod<string>();
}
}
}
public class LuaCallCs : MonoBehaviour
{
LuaEnv luaenv = null;
string script = @"
function demo()
--new C#對象
local newGameObj = CS.UnityEngine.GameObject()
local newGameObj2 = CS.UnityEngine.GameObject('helloworld')
print(newGameObj, newGameObj2)
--訪問靜態屬性,方法
local GameObject = CS.UnityEngine.GameObject
print('UnityEngine.Time.deltaTime:', CS.UnityEngine.Time.deltaTime) --讀靜態屬性
CS.UnityEngine.Time.timeScale = 0.5 --寫靜態屬性
print('helloworld', GameObject.Find('helloworld')) --靜態方法調用
--訪問成員屬性,方法
local DerivedClass = CS.Tutorial.DerivedClass
local testobj = DerivedClass()
testobj.DMF = 1024--設置成員屬性
print(testobj.DMF)--讀取成員屬性
testobj:DMFunc()--成員方法
--基類屬性,方法
print(DerivedClass.BSF)--讀基類靜態屬性
DerivedClass.BSF = 2048--寫基類靜態屬性
DerivedClass.BSFunc();--基類靜態方法
print(testobj.BMF)--讀基類成員屬性
testobj.BMF = 4096--寫基類成員屬性
testobj:BMFunc()--基類方法調用
--複雜方法調用
local ret, p2, p3, csfunc = testobj:ComplexFunc({x=3, y = 'john'}, 100, function()
print('i am lua callback')
end)
print('ComplexFunc ret:', ret, p2, p3, csfunc)
csfunc()
--重載方法調用
testobj:TestFunc(100)
testobj:TestFunc('hello')
--操作符
local testobj2 = DerivedClass()
testobj2.DMF = 2048
print('(testobj + testobj2).DMF = ', (testobj + testobj2).DMF)
--默認值
testobj:DefaultValueFunc(1)
testobj:DefaultValueFunc(3, 'hello', 'john')
--可變參數
testobj:VariableParamsFunc(5, 'hello', 'john')
--Extension methods
print(testobj:GetSomeData())
print(testobj:GetSomeBaseData()) --訪問基類的Extension methods
testobj:GenericMethodOfString() --通過Extension methods實現訪問泛化方法
--枚舉類型
local e = testobj:EnumTestFunc(CS.Tutorial.TestEnum.E1)
print(e, e == CS.Tutorial.TestEnum.E2)
print(CS.Tutorial.TestEnum.__CastFrom(1), CS.Tutorial.TestEnum.__CastFrom('E1'))
print(CS.Tutorial.DerivedClass.TestEnumInner.E3)
assert(CS.Tutorial.BaseClass.TestEnumInner == nil)
--Delegate
testobj.TestDelegate('hello') --直接調用
local function lua_delegate(str)
print('TestDelegate in lua:', str)
end
testobj.TestDelegate = lua_delegate + testobj.TestDelegate --combine,這裏演示的是C#delegate作爲右值,左值也支持
testobj.TestDelegate('hello')
testobj.TestDelegate = testobj.TestDelegate - lua_delegate --remove
testobj.TestDelegate('hello')
--事件
local function lua_event_callback1() print('lua_event_callback1') end
local function lua_event_callback2() print('lua_event_callback2') end
testobj:TestEvent('+', lua_event_callback1)
testobj:CallEvent()
testobj:TestEvent('+', lua_event_callback2)
testobj:CallEvent()
testobj:TestEvent('-', lua_event_callback1)
testobj:CallEvent()
testobj:TestEvent('-', lua_event_callback2)
--64位支持
local l = testobj:TestLong(11)
print(type(l), l, l + 100, 10000 + l)
--typeof
newGameObj:AddComponent(typeof(CS.UnityEngine.ParticleSystem))
--cast
local calc = testobj:GetCalc()
print('assess instance of InnerCalc via reflection', calc:add(1, 2))
assert(calc.id == 100)
cast(calc, typeof(CS.Tutorial.ICalc))
print('cast to interface ICalc', calc:add(1, 2))
assert(calc.id == nil)
end
demo()
--協程下使用
local co = coroutine.create(function()
print('------------------------------------------------------')
demo()
end)
assert(coroutine.resume(co))
";
// Use this for initialization
void Start()
{
luaenv = new LuaEnv();
luaenv.DoString(script);
}
// Update is called once per frame
void Update()
{
if (luaenv != null)
{
luaenv.Tick();
}
}
void OnDestroy()
{
luaenv.Dispose();
}
}
/////////////////////////////////////////////////////////////////////////////