【XLua】020-Lua訪問(wèn)C#:其他使用說(shuō)明


其他的使用

其他的使用方式參見官方實(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ì)象。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Lua 5.1 參考手冊(cè) by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 14,243評(píng)論 0 38
  • 將下列代碼掛載到任何一個(gè)GameObject上,這樣就能在Unity中加載并執(zhí)行Resources/Lua文件夾下...
    BlauHimmel閱讀 23,557評(píng)論 3 18
  • 名稱 說(shuō)明 docLua 相關(guān)的文檔,包括了編譯文檔、接口文檔等 Makefile 編譯Lua使用,在...
    一川煙草i蓑衣閱讀 1,636評(píng)論 0 1
  • 高一高二那些不安分的同學(xué)們,我心里有些話,憋在心里已經(jīng)半個(gè)月了,我真的想找個(gè)機(jī)會(huì)能夠說(shuō)給大家聽聽。但是,卻一直沒(méi)有...
    雪后山閱讀 533評(píng)論 2 14
  • 夜將盡未盡時(shí),出發(fā)。 經(jīng)過(guò)剪子灣梁子,到達(dá)了雅江縣和理塘縣的分界點(diǎn)——卡子拉山。 卡子拉山海拔近5000米,我連車...
    眼里的湖閱讀 810評(píng)論 0 3

友情鏈接更多精彩內(nèi)容