

其他的使用
其他的使用方式參見官方實(shí)例如下:
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("Driven Static Func, BSF = "+ BSF);
}
public static int BSF = 1;
public void BMFunc()
{
Debug.Log("Driven 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 DrivenClass : BaseClass
{
[LuaCallCSharp]
public enum TestEnumInner
{
E3,
E4
}
public void DMFunc()
{
Debug.Log("Driven 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 DrivenClass operator +(DrivenClass a, DrivenClass b)
{
DrivenClass ret = new DrivenClass();
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 DrivenClassExtensions
{
public static int GetSomeData(this DrivenClass 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 DrivenClass obj)
{
obj.GenericMethod<string>();
}
}
}
public class LuaCallCs : MonoBehaviour {
LuaEnv luaenv = null;
string script = @"
function demo()
--new C#對(duì)象
local newGameObj = CS.UnityEngine.GameObject()
local newGameObj2 = CS.UnityEngine.GameObject('helloworld')
print(newGameObj, newGameObj2)
--訪問(wèn)靜態(tài)屬性,方法
local GameObject = CS.UnityEngine.GameObject
print('UnityEngine.Time.deltaTime:', CS.UnityEngine.Time.deltaTime) --讀靜態(tài)屬性
CS.UnityEngine.Time.timeScale = 0.5 --寫靜態(tài)屬性
print('helloworld', GameObject.Find('helloworld')) --靜態(tài)方法調(diào)用
--訪問(wèn)成員屬性,方法
local DrivenClass = CS.Tutorial.DrivenClass
local testobj = DrivenClass()
testobj.DMF = 1024--設(shè)置成員屬性
print(testobj.DMF)--讀取成員屬性
testobj:DMFunc()--成員方法
--基類屬性,方法
print(DrivenClass.BSF)--讀基類靜態(tài)屬性
DrivenClass.BSF = 2048--寫基類靜態(tài)屬性
DrivenClass.BSFunc();--基類靜態(tài)方法
print(testobj.BMF)--讀基類成員屬性
testobj.BMF = 4096--寫基類成員屬性
testobj:BMFunc()--基類方法調(diào)用
--復(fù)雜方法調(diào)用
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()
--重載方法調(diào)用
testobj:TestFunc(100)
testobj:TestFunc('hello')
--操作符
local testobj2 = DrivenClass()
testobj2.DMF = 2048
print('(testobj + testobj2).DMF = ', (testobj + testobj2).DMF)
--默認(rèn)值
testobj:DefaultValueFunc(1)
testobj:DefaultValueFunc(3, 'hello', 'john')
--可變參數(shù)
testobj:VariableParamsFunc(5, 'hello', 'john')
--Extension methods
print(testobj:GetSomeData())
print(testobj:GetSomeBaseData()) --訪問(wèn)基類的Extension methods
testobj:GenericMethodOfString() --通過(guò)Extension methods實(shí)現(xiàn)訪問(wèn)泛化方法
--枚舉類型
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.DrivenClass.TestEnumInner.E3)
assert(CS.Tutorial.BaseClass.TestEnumInner == nil)
--Delegate
testobj.TestDelegate('hello') --直接調(diào)用
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()
--協(xié)程下使用
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();
}
}
其他使用方式的文檔說(shuō)明:
-
操作符
支持的操作符有:+,-,*,/,==,一元-,<,<=, %,[]
-
參數(shù)帶默認(rèn)值的方法
和C#調(diào)用有默認(rèn)值參數(shù)的函數(shù)一樣,如果所給的實(shí)參少于形參,則會(huì)用默認(rèn)值補(bǔ)上。
-
可變參數(shù)方法
對(duì)于C#的如下方法:
void VariableParamsFunc(int a, params string[] strs)
可以在lua里頭這樣調(diào)用:
testobj:VariableParamsFunc(5, 'hello', 'john')
使用Extension methods
在C#里定義了,lua里就能直接使用。
-
泛化(模版)方法
不直接支持,可以通過(guò)Extension methods功能進(jìn)行封裝后調(diào)用。
-
枚舉類型
枚舉值就像枚舉類型下的靜態(tài)屬性一樣。
testobj:EnumTestFunc(CS.Tutorial.TestEnum.E1)
上面的EnumTestFunc函數(shù)參數(shù)是Tutorial.TestEnum類型的
另外,如果枚舉類加入到生成代碼的話,枚舉類將支持__CastFrom方法,可以實(shí)現(xiàn)從一個(gè)整數(shù)或者字符串到枚舉值的轉(zhuǎn)換,例如:
CS.Tutorial.TestEnum.__CastFrom(1)
CS.Tutorial.TestEnum.__CastFrom('E1')
-
delegate使用(調(diào)用,+,-)
C#的delegate調(diào)用:和調(diào)用普通lua函數(shù)一樣
+操作符:對(duì)應(yīng)C#的+操作符,把兩個(gè)調(diào)用串成一個(gè)調(diào)用鏈,右操作數(shù)可以是同類型的C# delegate或者是lua函數(shù)。
-操作符:和+相反,把一個(gè)delegate從調(diào)用鏈中移除。
Ps:delegate屬性可以用一個(gè)luafunction來(lái)賦值。
-
event
比如testobj里頭有個(gè)事件定義是這樣:public event Action TestEvent;
增加事件回調(diào)
testobj:TestEvent('+', lua_event_callback)
移除事件回調(diào)
testobj:TestEvent('-', lua_event_callback)
-
64位整數(shù)支持
Lua53版本64位整數(shù)(long,ulong)映射到原生的64未整數(shù),而luaji版本t,相當(dāng)于lua5.1的標(biāo)準(zhǔn),本身不支持64位,xlua做了個(gè)64位支持的擴(kuò)展庫(kù),C#的long和ulong都將映射到userdata:
1、支持在lua里頭進(jìn)行64位的運(yùn)算,比較,打印
2、支持和lua number的運(yùn)算,比較
3、要注意的是,在64擴(kuò)展庫(kù)中,實(shí)際上只有int64,ulong也會(huì)先強(qiáng)轉(zhuǎn)成long再傳遞到lua,而對(duì)ulong的一些運(yùn)算,比較,我們采取和java一樣的支持方式,提供一組API,詳情請(qǐng)看API文檔。
-
C#復(fù)雜類型和table的自動(dòng)轉(zhuǎn)換
對(duì)于一個(gè)有無(wú)參構(gòu)造函數(shù)的C#復(fù)雜類型,在lua側(cè)可以直接用一個(gè)table來(lái)代替,該table對(duì)應(yīng)復(fù)雜類型的public字段有相應(yīng)字段即可,支持函數(shù)參數(shù)傳遞,屬性賦值等,例如:
C#下B結(jié)構(gòu)體(class也支持)定義如下:
public struct A
{
public int a;
}
public struct B
{
public A b;
public double c;
}
某個(gè)類有成員函數(shù)如下:
void Foo(B b)
在lua可以這么調(diào)用
obj:Foo({b = {a = 100}, c = 200})
-
獲取類型(相當(dāng)于C#的typeof)
比如要獲取UnityEngine.ParticleSystem類的Type信息,可以這樣
typeof(CS.UnityEngine.ParticleSystem)
-
“強(qiáng)”轉(zhuǎn)
lua沒(méi)類型,所以不會(huì)有強(qiáng)類型語(yǔ)言的“強(qiáng)轉(zhuǎn)”,但有個(gè)有點(diǎn)像的東西:告訴xlua要用指定的生成代碼去調(diào)用一個(gè)對(duì)象,這在什么情況下能用到呢?有的時(shí)候第三方庫(kù)對(duì)外暴露的是一個(gè)interface或者抽象類,實(shí)現(xiàn)類是隱藏的,這樣我們無(wú)法對(duì)實(shí)現(xiàn)類進(jìn)行代碼生成。該實(shí)現(xiàn)類將會(huì)被xlua識(shí)別為未生成代碼而用反射來(lái)訪問(wèn),如果這個(gè)調(diào)用是很頻繁的話還是很影響性能的,這時(shí)我們就可以把這個(gè)interface或者抽象類加到生成代碼,然后指定用該生成代碼來(lái)訪問(wèn):
cast(calc, typeof(CS.Tutorial.Calc))
上面就是指定用CS.Tutorial.Calc的生成代碼來(lái)訪問(wèn)calc對(duì)象。