xLua笔记(热更新框架设计之Xlua基础)

热 更新的 基本原理

 C#脚本不能直接热更新的原因:

下载的图片与模型都没有问题,如果是Unity逻辑代码,无论是以前的

Mono AOT 还是后面的il2cpp , 都是编译成native code, IOS下是运行不起

来的。

 解决方法

就是不用native code ,改为解释执行。包括Xlua在内所有热更新就是这

个思路来实现。

 

Xlua插件的GitHub 下载地址

https://github.com/Tencent/xLua

 作者对于Xlua插件的整体介绍性文章

扫描二维码关注公众号,回复: 4666119 查看本文章

http://www.gad.qq.com/article/detail/24967

 

具体准备开发环境:

1:下载Xlua插件,且导入工程。

2: 把Xlua中的Xlua与Plugins 目录直接拷贝到项目所在文件夹。成功拷贝后,

在Unity菜单中可以看到出现"XLua"的菜单项。


1.lua中使用冒号“:”表示成员方法的调用。它自动完成当前对象作为一个参数,传入方法;lua中使用点“.”,则表示静态属性与方法调用,它需要手工往方法中传递当前对象。

2.冒号定义方法,默认会接受self参数,而点号定义的时候,默认不会接受self参数

3.lua中 classObj:Method()与 classObj.Method(classObj)一样

 

1.lua 的字段或者函数之间要用 ,(逗号)隔开

 

2.lua里面的类或者table可以映射到C#里面的Interface,C#里面的Interface要用public修饰,并且要添加[CSharpCallLua]特性标签

 

3.加载Resources文件里面的lua文件:

 

  a.   env = new LuaEnv();

 

        env.DoString("require 'LuaCallCSharp'");

  b. env = new LuaEnv();

       TextAsset txtAsset = Resources.Load<TextAsset>("simpleLua.lua");

       env.DoString(txtAsset.text);

 

  c. LuaEnv env = null;

    // Use this for initialization

 

    string fileName = "CustomDIRLuaFile";

    void Start()

    {

        env = new LuaEnv();

        env.AddLoader(CustomMyLoader);

        env.DoString("require 'CustomDIRLuaFile'");

    }

 

    byte[] CustomMyLoader(ref string fileName)

    {

        string luaPath = Application.dataPath + "/Scripts/LuaScripts/" + fileName + ".lua";

 

        string strLuaContent = File.ReadAllText(luaPath);

 

        byte[] back=null;

        back = System.Text.Encoding.UTF8.GetBytes(strLuaContent);

        return back;

    }

 

uv:告诉贴图如何贴在模型上

 

反转法线

高亮 unlit/texture

 

                使用

1. 最基本是直接用LuaEnv.DoString执行一个字符串,当然,字符串得符合Lua语法

比如:luaenv.DoString("print('hello world')")

2. 加载 lua 文件

 使用TextAsset 方式加载文件:

Eg:

TextAsset ta=Resources.Load<TextAsset>("HelloWorld.lua");

LuaEnv env=new LuaEnv();

env.DoString(ta.text);

 

3. 加载 lua 文件

 Require函数进行加载 (常用方式)

require 就是一个个的调用Loader ,查找出匹配的lua文件,然后执行

该文件。

注意事项:

1:因为Resource 只支持有限的后缀,放Resource下的lua文件需要加上

txt后缀。

2:使用lua开发项目推荐的方式是:整个程序就一个

DoString(“require‘main’”), 然后在main.lua中加载其他脚本。(这里

的Main文件名称可以任意)

3. 在xLua加自定义loader是很简单的,只涉及到一个接口:

public delegate byte[] CustomLoader(ref string filepath);

public void LuaEnv.AddLoader(CustomLoader loader)

通过AddLoader可以注册个回调,该回调参数是字符串,lua代码里头调用require时,参数将会透传给回调,回调中就可以根据这个参数去加载指定文件,如果需要支持调试,需要把filepath修改为真实路径传出。该回调返回值是一个byte数组,如果为空表示该loader找不到,否则则为lua文件的内容。如下:

//lua环境(官方建议全局唯一)

LuaEnv env = null;

private void Start()

{

env = new LuaEnv();

env.AddLoader(CustomMyLoader);

env.DoString("require 'CustomDIRLuaFile'");

}

/// <summary>

/// 定义回调方法

/// 功能:

///     本方法主要功能是自定义lua文件路径。

/// </summary>

/// <param name="fileName">文件名称</param>

/// <returns></returns>

private byte[] CustomMyLoader(ref string fileName)

{

byte[] byArrayReturn = null; //返回数据

//定义lua路径

string luaPath = Application.dataPath + "/Scripts/LuaScripts/" + fileName + ".lua";

//读取lua路径中指定lua文件内容

string strLuaContent = File.ReadAllText(luaPath);

//数据类型转换

byArrayReturn = System.Text.Encoding.UTF8.GetBytes(strLuaContent);

return byArrayReturn;

}

 

不同lua文件的加载方式分析:

 使用Require 方式加载lua文件,必须放置在Resources特殊目录下,否则

查找不到无法加载。

 自定义Loader 可以进一步扩展前面两种方法的弊端,可以按照自己的方

式进行加载lua与执行lua代码。(即:可以把*.lua文件放置到任意合法文

件夹下,且lua文件不用后缀增加txt标识。)

 require 本质是按照既定的查找顺序,找到需要的lua程序,否则返回

nil ,然后报错。演示当查找一个错误的lua文件时候,控制台详细打印的

查找路径。

C#调用lua

Lua类:

--定义一个综合表(lua中的OOP思想)属性或方法中以逗号分隔

gameUser={

       name="崔永元",

       age=40,

       ID="18011112222",

       Speak=function()

              print("lua玩家在讨论中")

       end,

       Walking=function()

              print("lua玩家在健身中")

       end,

       Calulation=function(age,num1,num2)--说明:age 这里命名可以任意,表示当前对象(即:gameUser)

              return age.age+num1+num2

       end

}

 

1. 获取 一个全局基本 数据类型

 访问LuaEnv.Global就可以了,上面有个模版Get方法,可指定返回的类型。

env = new LuaEnv();

            env.DoString("require 'CsharpCallLua'");

            string str1=env.Global.Get<string>("str");  //字符串类型

            int num = env.Global.Get<int>("number");//数字类型

 

2. 访问一个全局 table
方式1: 映射到普通class或struct

定义一个class,有对应于table的字段的public属性,而且有无参数构

造函数即可,比如对于{f1 = 100, f2 = 100}可以定义一个包含

public int f1;

public int f2; 的class。

这种方式下xLua会帮你new一个实例,并把对应的字段赋值过去。

table的属性可以多于或者少于class的属性。可以嵌套其它复杂类型。

 

方式2:映射到一个interface [*推荐方式]

这种方式依赖于生成代码(如果没生成代码会抛InvalidCastException异

常),代码生成器会生成这个interface的实例。 如果get一个属性,生成代

码会get对应的table字段,如果set属性也会设置对应的字段。甚至可以通过

interface的方法访问lua的函数。

注意点与性能分析:

A: 接口需要添加特性标签[CSharpCallLua],否则无法生成实例代码。

B: 为引用拷贝,适合用在复杂表,一般商业项目推荐使用本方式。

如下:

//定义接口

        [CSharpCallLua]

        public interface IGameLanguage

        {

            string str1 { get; set; }

            string str2 { get; set; }

            string str3 { get; set; }

            string str4 { get; set; }

        }

  //lua环境(官方建议全局唯一)

        LuaEnv env = null;

 

        private void Start()

        {

            env = new LuaEnv();

            env.DoString("require 'CsharpCallLua'");

            //得到lua中的表信息

            IGameLanguage gameLan = env.Global.Get<IGameLanguage>("gameLanguage");

            //输出显示

            Debug.Log("[使用接口]gameLan.str1="+ gameLan.str1);

            Debug.Log("[使用接口]gameLan.str2=" + gameLan.str2);

            Debug.Log("[使用接口]gameLan.str3=" + gameLan.str3);

            Debug.Log("[使用接口]gameLan.str4=" + gameLan.str4);

            //演示接口的引用拷贝原理

            gameLan.str1 = "我是修改后的内容";

            env.DoString("print('修改后gameLanguage.str1='..gameLanguage.str1)");

 

        }

 

 

Example: 通过interface ,调用lua中一个复杂一些的Table

public class CallLuaTableByInterfaceComp:MonoBehaviour

    {

        //lua环境(官方建议全局唯一)

        LuaEnv env = null;

 

        private void Start()

        {

            env = new LuaEnv();

            env.DoString("require 'CsharpCallLua'");

            //得到lua中的表信息

            IGameUser gameUser = env.Global.Get<IGameUser>("gameUser");

            //输出显示

            Debug.Log("[使用接口]gameLan.ID=" + gameUser.ID);

            Debug.Log("[使用接口]gameLan.Name=" + gameUser.name);

            Debug.Log("[使用接口]gameLan.Age=" + gameUser.age);

 

            //输出调用方法

            gameUser.Speak();

            gameUser.Walking();

            int tmpResult=gameUser.Calulation(100,200);

            Debug.Log("经过lua中计算,结果= "+tmpResult);

 

        }

 

        private void OnDestroy()

        {

            //释放luaenv

            env.Dispose();

        }

 

        //定义接口

        [CSharpCallLua]

        public interface IGameUser

        {

            string name { get; set; }

            int age { get; set; }

            string ID { get; set; }

 

            void Speak();

            void Walking();

            int Calulation(int num1, int num2);

 

        }

    }

方式3: by value 方式:

这是更轻量级的by value 方式,映射到Dictionary<>,List<> (适合用在

简单表)不想定义class或者interface的话,可以考虑用这个,前提table下

key和value的类型都是一致的。如下:

//得到lua中的简单表信息

Dictionary<string, object>  dicGameLan=env.Global.Get<Dictionary<string, object>>("gameLanguage");//映射一个简单表

 

            //得到lua中的复杂表信

Dictionary<string, object>  dicGameLan=env.Global.Get<Dictionary<string, object>>("gameUser");//映射一个复杂表


//得到一个更加简单lua表,使用List<> 来映射。

List<string> liProLan=env.Global.Get<List<string>>("programLanguage");

 

Example:  讲解使用委托的方式,调用Lua中具备多个返回数值的函数。

 *          1: 定义out 关键字的委托。

 *          2:定义ref 关键字的委托。
 

  //自定义委托(使用out关键字)

    [CSharpCallLua]

    public delegate void delAddingMutilReturn(int num1, int num2, out int res1, out int res2, out int res3);

    [CSharpCallLua]

    public delegate void delAddingMutilRetRef(ref int num1, ref int num2, out int result);

 

    public class CallLuaFunctionByDeleMultiReturn:MonoBehaviour

    {

        //lua环境(官方建议全局唯一)

        LuaEnv env = null;

        //委托声明

        delAddingMutilReturn act1 = null;

        delAddingMutilRetRef act2 = null;

 

        private void Start()

        {

            env = new LuaEnv();

            env.DoString("require 'CsharpCallLua'");

            ////得到lua中的具有多个返回数值的函数(通过委托out关键字来进行映射)

            //act1=env.Global.Get<delAddingMutilReturn>("ProcMyFunc5");

 

            ////输出返回结果

            //int intOutRes1 = 0;

            //int intOutRes2 = 0;

            //int intOutRes3 = 0;

            //act1(100, 880,out intOutRes1, out intOutRes2, out intOutRes3);

            //Debug.Log(string.Format("res1={0},res2={1},res3={2}", intOutRes1, intOutRes2, intOutRes3));

 

            //得到lua中的具有多个返回数值的函数(通过委托ref关键字来进行映射)

            act2=env.Global.Get<delAddingMutilRetRef>("ProcMyFunc5");

 

            //输出返回结果

            int intNum1 = 20;

            int intNum2 = 30;

            int intResult = 0;

 

            act2(ref intNum1, ref intNum2, out intResult);

            Debug.Log(string.Format("使用ref关键字,测试多输出 res1={0},res2={1},res3={2}", intNum1,intNum2, intResult));

        }


方式4: by ref方式,映射到LuaTable类。

这种方式好处是不需要生成代码,但问题就是比较慢(即:效率低下),

比interface方式要慢一个数量级,比如没有类型检查。

性能分析:

因为效率较低,所以不推荐常用,适合用在一些较为复杂且使用频率很

低的情况下,一般不推荐使用。如下:

env = new LuaEnv();

            env.DoString("require 'CsharpCallLua'");

            //得到lua中的复杂表信息

            XLua.LuaTable tabGameUser=env.Global.Get<XLua.LuaTable>("gameUser");

 

            //输出显示

            Debug.Log("name="+tabGameUser.Get<string>("name"));

            Debug.Log("Age=" + tabGameUser.Get<int>("age"));

            Debug.Log("ID=" + tabGameUser.Get<string>("ID"));

 

            //输出表中函数

            XLua.LuaFunction funSpeak=tabGameUser.Get<XLua.LuaFunction>("Speak");

            funSpeak.Call();

            XLua.LuaFunction funWalking = tabGameUser.Get<XLua.LuaFunction>("Walking");

            funWalking.Call();

 

            XLua.LuaFunction funCalulation = tabGameUser.Get<XLua.LuaFunction>("Calulation");

            object[] objArray=funCalulation.Call(tabGameUser, 10, 20);

            Debug.Log("输出结果="+ objArray[0]);//输出结果: 70

 

2. 访问 一个全局的
方式1: 映射到delegate [* 推荐方式]

优点: 这是建议的方式,性能好很多,而且类型安全。

缺点: (含有out与ref关键字delegate)要生成代码(如果没生成代码会抛

InvalidCastException异常)。

注意:

A: 含有 out 与 ref 关键字委托也需要添加特性标签[ [ CSharpCallLua] ]

B: 委托 引用后,退出 luaEnv 前,需要释放委托引用,否则 lua 报错 !

C: 对于 Unity 与 C# 中的复杂类型 API, 必须加入 Xlua 的配置文件,经过生

成代码后才能正确应用。

例如: Action< int,int,int > 、 Func< < int,int,int >


delegate要怎样声明呢?

对于function的每个参数就声明一个输入类型的参数。

多返回值要怎么处理?

从左往右映射到c#的输出参数,输出参数包括返回值,out参数,ref参

数。

参数、返回值类型支持哪些呢?

都支持,各种复杂类型,out,ref修饰的,甚至可以返回另外一个

delegate

public class CallLuaFunctionByDele:MonoBehaviour

    {

        //lua环境(官方建议全局唯一)

        LuaEnv env = null;

        //自定义委托

        public delegate void delAdding(int num1, int num2);

        Action act = null;

        delAdding act2 = null;

        //注意: 以下两种委托定义,需要配置文件支持。

        Action<int, int, int> act3 = null;

        Func<int, int, int> act4 = null;

 

 

        private void Start()

        {

            env = new LuaEnv();

            env.DoString("require 'CsharpCallLua'");

            //得到lua中的函数信息(通过委托来进行映射)

            act=env.Global.Get<Action>("ProcMyFunc1");

            //使用自定义委托调用具备两个输入参数的lua中的函数

            act2=env.Global.Get<delAdding>("ProcMyFunc2");

            //定义三个输入参数的委托。

            act3 = env.Global.Get<Action<int, int, int>>("ProcMyFunc4");

            //定义具备返回数值,两个输入数值的委托

            act4 = env.Global.Get<Func<int, int, int>>("ProcMyFunc3");

 

            //调用

            act.Invoke();

            act2(50,60);

            act3(20, 30, 40);

            int intResult=act4(60,40);

            Debug.Log("Func 委托,输出结果="+intResult);

 

        }

        private void OnDestroy()

        {

            act = null;

            act2 = null;

            act3 = null;

            act4 = null;

            //释放luaenv

            env.Dispose();

        }

}

 

方式2: 映射到LuaFunction

优点: 无需生成代码

缺点: 性能不高,不推荐。

这种方式的优缺点刚好和第一种相反。使用也简单。LuaFunction上有个

变参的Call函数,可以传任意类型,任意个数的参数,返回值是object的数

组,对应于lua的多返回值。

private void Start()

        {

            env = new LuaEnv();

            env.DoString("require 'CsharpCallLua'");

            //得到lua中的函数信息(通过LuaFunction来进行映射)

            LuaFunction luaFun=env.Global.Get<LuaFunction>("ProcMyFunc1");

            LuaFunction luaFun2 = env.Global.Get<LuaFunction>("ProcMyFunc2");

            LuaFunction luaFun3 = env.Global.Get<LuaFunction>("ProcMyFunc3");

            //调用具有多返回数值。

            LuaFunction luaFun4 = env.Global.Get<LuaFunction>("ProcMyFunc5");

 

            //输出

            luaFun.Call();

            luaFun2.Call(10, 20);

            object[] objArray = luaFun3.Call(30, 40);

            Debug.Log("调用ProcMyFunc3 ,结果=" + objArray[0]);

 

            object[] objArray2=luaFun4.Call(22,80);

            Debug.Log(string.Format("测试多返回数值 res1={0},res2={1},res3={2}",objArray2[0], objArray2[1], objArray2[2]));

 

        }

 

官方使用建议:

A: 访问lua全局数据,特别是table以及function,代价比较大,建议

尽量少做,比如在初始化时把要调用的lua function获取一次(映射到

delegate)后,保存下来,后续直接调用该delegate即可。table也类似。

B: 如果lua实现的部分都以delegate和interface的方式提供,使用方

可以完全和xLua解耦: 由一个专门的模块负责xlua的初始化以及delegate、

interface的映射,然后把这些delegate和interface设置到要用到它们的地

方。

 

 

Lua调用C#

1. lua 访问 C# 静态属性与 方法
基本方法:

使用CS开头,实例化类。

在C#这样new一个对象:

var newGameObj = new UnityEngine.GameObject();

对应到Lua是这样:

local newGameObj = CS.UnityEngine.GameObject()
基本规则:

A: lua里头没有new关键字。

B: 所有C#相关的都放到CS下,包括构造函数,静态成员属性、方法。

 如果有多个构造函数呢?

xlua支持重载,比如你要调用GameObject的带一个string参数的构造函

数,这么写:

local newGameObj2 = CS.UnityEngine.GameObject('helloworld')
 

2. lua 访问 C# 常用方式
 1. 方式1:访问成员属性与方法

读成员属性 testobj.DMF

写成员属性 testobj.DMF = 1024

调用成员方法 testobj:DMFunc()

注意:

lua中使用冒号,表示成员方法的调用。它自动完成把当前对象作为一

个参数,传入方法。

lua中使用点,则表示静态属性与方法调用。它需要手工往方法中传递

当前对象。

 

2. 方式2:访问父类属性与方法

xlua支持(通过派生类)访问基类的静态属性,静态方法,(通过派生

类实例)访问基类的成员属性,成员方法。

 

3. 方式3: 访问重载方法

Xlua 支持方法的重载,但为“有限重载”。直接通过不同的参数类型进

行重载函数的访问,例如:

testobj:TestFunc(100)

testobj:TestFunc('hello')

将分别访问整数参数的TestFunc和字符串参数的TestFunc。
 

注意:

xlua只一定程度上支持重载函数的调用,因为lua的类型远远不如C#丰富,

存在一对多的情况,

比如C#的int,float,double都对应于lua的number,上面的例子中

TestFunc如果有这些重载参数,第一行将无法区分开来,只能调用到其中一

个(生成代码中排前面的那个)

 

 

3. lua 调用 C# 中带参方法

 1. 方式1: C# 中可变参数方法

对于C#的如下方法:

void VariableParamsFunc(int a, params string[] strs)

可以在lua里头这样调用:

testobj:VariableParamsFunc(5, 'hello', 'john')

 

 2. 方式2: C#结构体参数

lua 使用一个表,来映射C#的结构体。

 

 3. 方式3:C#接口参数

注意: 接口需要加入标记: [CSharpCallLua]

lua 使用一个表,来映射C#的接口。

 

 4. 方式4: C#委托参数

委托需要加入标记: [CSharpCallLua]

lua 使用一个函数,来映射C#的委托。

 

4. lua 接收 C# 方法返回的多个结果数值
 1. 基本规则: 参数的输入输出属性(out,ref)

A: C#的普通参数算一个输入形参,ref修饰的算一个输入形参,out不算,

然后从左往右对应lua 调用的实参列表。

B: Lua调用返回值处理规则:

C#函数的返回值(如果有的话)算一个返回值,out算一个返回值,

ref算一个返回值,然后从左往右对应lua的多返回值。

 

5. lua 如何调用 C# 泛型方法
  基本规则:

lua 不直接支持C#的泛型方法,但可以通过扩展方法功能进行封装后调

用。

 使用 Extension methods (扩展方法)技术就是C#中在不改变原始类的基

础上,使用一种机制可以无限扩展这个类功能的机制。

Eg:

原始类为: A 扩展类为: Ext_A

注意: Ext_A 必须是一个静态类,且扩展方法也必须是静态的。方法的

参数中必须要有被扩展类作为其中一个参数,此参数前面必须有this 关键字

修饰。
 

6.Lua 调用其他 C# 知识点
  1. 参数带默认值的方法

与C#调用有默认值参数的函数一样,如果所给的实参少于形参,则会

用默认值补上。

 枚举类型

枚举值就像枚举类型下的静态属性一样。

testobj:EnumTestFunc(CS.Tutorial.TestEnum.E1)

上面的EnumTestFunc函数参数是Tutorial.TestEnum类型的

 

 2. 委托与事件

delegate 属性可以用一个luaFunction 来赋值(前面已经讲过)

比如testobj里头有个事件定义是这样:public event Action

TestEvent;

增加事件回调

testobj:TestEvent('+', lua_event_callback)

移除事件回调

testobj:TestEvent('-', lua_event_callback)

 

委托与事件(续)

delegate 使用 (调用,+,-)

注意:

A: 这里lua中可以使用“+/-”操作符,来增加与减少一个委托的调用。

B: delegate 属性可以用一个 luafunction 来赋值。

 

 委托与事件(续)

event使用

Eg:

public event Action TestEvent;

增加事件回调:

testObj: TestEvent('+',lua_event_callback)

移除事件回调:

testObj: TestEvent('-',lua_event_callback)

 

7. Lua 调用 C# 经验总结

 1. 一: lua 调用C#,需要在Xlua中生成“适配代码”,则在这个类打入一个

[luaCallCSharp] 的标签。

 二: 如果lua调用C#的系统API ,则无法拿到源代码,无法打入标签。则

使用“静态列表”方式解决。

Eg:

public static List<Type> mymodule_LuaCallCS_List=new

List<Type>()

{

typeof(GameObject),

typeof(Dictionary<string,int>),

};

然后把以上代码放入一个静态类中即可。

 

三: 实际开发过程中,lua 调用C# 用的比较多。

xlua 的优点体现的没有必要每次改的时候,都要生成代码。主要原理是

依赖于编译器环境下,利用反射来动态生成代码接口。

 四: 在标有“[XLua.LuaCallCSharp]”的C#类中,添加新的方法后,如

果是生成了代码类,则必须重新生成或者删除,否则Xlua 用以前生成的,

进行注册查询,会出现lua 异常:“试图访问一个nil 的方法”

 

 

 

LuaCallCsharp.lua文件

--详细演示 lua Call C# 各种特性

--

print("测试lua文件是否正确加载")

 

--[[  一: 学习 lua  调用 Unity 系统 API   ]]--

--1: lua 中实例化一个 Unity 的对象

local newGo=CS.UnityEngine.GameObject()

newGo.name="New GameObject"

 

--2: 查找游戏物体

--   学习lua 访问Unity API 中静态属性与方法

local TxtGo=CS.UnityEngine.GameObject.Find("Txt_Logo");

--TxtGo.name="Modify Name"

 

--3: 得到游戏对象上的组件,学习使用冒号与句号(":",“.”)

local txtLogo=TxtGo:GetComponent("UnityEngine.UI.Text")

txtLogo.text="公告系统"

 

 

--[[  二: 学习 lua  调用自定义C#脚本   ]]--

local IsInvoked=CS.XluaPro.IsInvokedClass

local classObj=IsInvoked()   --自动调用父类与子类的构造函数

 

--调用普通方法

--classObj:Mehtod1()                               --ok

--classObj.Mehtod1()                         --语法报错!

--classObj.Mehtod1(classObj)               --语法OK

 

--调用父类的字段与方法

--classObj:ShowFatherInfo();              --调用父类的方法

--print(classObj.FatherClassName)         --调用父类的公共字段

--print(classObj.ChildClassName)          --调用子类的公共字段

 

--测试调用C#方法重载

--classObj:Method2(10,20)

--classObj:Method2("abc","def")

 

--测试C#中带有params 关键字的方法

--local intResult=classObj:Method3(20,70,"Hello ","World","EveryOne")

--print("调用parmas关键字的方法,返回数值= "..intResult)

 

--测试lua调用C#中带有结构体参数的方法

--定义一个表

--myStructTable={x="C#语言",y="lua语言"}

--classObj:Method4(myStructTable)

 

 

--测试lua调用C#中带有接口参数的方法

--定义一个表

myInterfaceTable=

{

       x=1000,

       y=300,

 

       Speak=function()

              print("lua中 Speak 方法被调用!")

       end

}

--classObj:Method5(myInterfaceTable)

 

--定义lua调用C#中带有委托参数的方法

--定义函数

myDelegate=function(num)

       print("lua 中对应委托方法。参数num="..num)

end

--classObj:Method6(myDelegate)

 

 

--接收C#多返回数值

local num1=10

local num2=20

local res1,res2,res3=classObj:Method7(num1,num2)

--print("res1="..res1)  --输出结果: 110

--print("res2="..res2)  --输出结果: 3000

--print("res3="..res3)  --输出结果: 999

 

--lua中可以直接调用具有泛型为参数的方法

--myTable8={"lua语言","C#语言","C++语言"}

--classObj:Method8(myTable8); 

 

--让C#方法运行起来。

--classObj:Method_InvokeGenger()

 

--lua中直接调用C#中定义的泛型方法

--local maxNum=CS.XluaPro.MyGengerric:GetMax<int>(20,30)  --报语法错误

--print("maxNum="..maxNum)

 

 

--lua调用C#中一个测试方法

--测试C#中调用C#中的“扩展方法”

--classObj:Test8_InvokeExtensionMethod();

 

 

--演示: 在lua中通过调用"扩展方法",来间接完成对C#“泛型方法”功能的实现。

local maxNum=CS.XluaPro.MyGengerric():ExtGetMax(888,66)

print("[在lua中扩展方法调用] maxNum="..maxNum)

 

 

 

猜你喜欢

转载自blog.csdn.net/lizhenxiqnmlgb/article/details/84564892
今日推荐