Xlua Lua调用c#

启动Lua脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;

//本脚本启动Lua文件
public class LuaCallCsharpBase : MonoBehaviour {

    LuaEnv env = null;

    private void Start()
    {
        env = new LuaEnv();
        env.DoString("require 'LuaCallCSharp'"); //LuaCallCSharp.lua.txt
    }

    private void OnDestroy()
    {
        env.Dispose();
    }
}

 

 

LuaCallCSharp.lua.txt

 

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

--[[  一: 学习 lua  调用 Unity 系统 API   ]]--
-- 所有C#相关的都放到CS下,包括构造函数,静态成员属性、方法。
--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#脚本   ]]--
--lua中使用冒号,表示成员方法的调用。它自动完成把当前对象作为一个参数,传入方法。
--lua中使用点,则表示静态属性与方法调用。它需要手工往方法中传递当前对象
--类
--如果有命名空间CS后面要加命名空间,比如CS.XluaPro.IsInvokedClass(XluaPro为命名空间)
local IsInvoked=CS.IsInvokedClass
--实例化
local classObj=IsInvoked()   --自动调用父类与子类的构造函数

--调用普通方法
classObj:Mehtod1()					--ok
--classObj.Mehtod1()			        --语法报错!
classObj.Mehtod1(classObj)		    --语法OK

--调用父类的字段与方法
classObj:ShowFatherInfo();              --调用父类的方法
print(classObj.FatherClassName)         --调用父类的公共字段
print(classObj.ChildClassName)          --调用子类的公共字段

--测试调用C#方法重载
--有限重载,无法区分浮点和整型,精度,调用的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#中带有结构体参数的方法
--lua 使用一个表,来映射C#的结构体。
--定义一个表
myStructTable={x="C#语言",y="lua语言"}
classObj:Method4(myStructTable)


--测试lua调用C#中带有接口参数的方法
--lua 使用一个表,来映射C#的接口。
--Unity里面要生成代码
--定义一个表
myInterfaceTable=
{
	x=1000,
	y=300,

	Speak=function()
		print("lua中 Speak 方法被调用!")
	end
}
classObj:Method5(myInterfaceTable)

--定义lua调用C#中带有委托参数的方法
--Unity里面要生成代码
--定义函数
myDelegate=function(num)
	print("lua 中对应委托方法。参数num="..num)
end
classObj:Method6(myDelegate)


--接收C#多返回数值
--C#函数的返回值(如果有的话)算一个返回值,out算一个返回值,
--   ref算一个返回值,然后从左往右对应lua的多返回值。
local num1=10
local num2=20
local res1,res2,res3=classObj:Method7(num1,num2)
--res1是返回值,res2和res3按参数顺序对应有out或者ref的参数
print("res1="..res1)  --输出结果: 110
print("res2="..res2)  --输出结果: 3000
print("res3="..res3)  --输出结果: 999


--lua中可以直接调用具有泛型为参数的方法
myTable8={"lua语言","C#语言","C++语言"}
classObj:Method8(myTable8);  


--通过另外定义一个方法(Method_InvokeGenger)来调用泛型方法
--让C#方法运行起来。
classObj:Method_InvokeGenger()

--lua中直接调用C#中定义的泛型方法 (错误)
--local maxNum=CS.XluaPro.MyGengerric:GetMax(20,30)  --报语法错误
--print("maxNum="..maxNum)

--lua调用C#中一个测试方法
--c#定义一个方法,在方法内通过c#的扩展方法来调用泛型方法,
classObj:Test8_InvokeExtensionMethod();


--演示: 在lua中通过调用"扩展方法",来间接完成对C#“泛型方法”功能的实现。
				--  可以重载多个扩展方法来应用不同类型
--c#带有泛型方法的类和扩展类都要加上 [XLua.LuaCallCSharp]
--然后 重新生成代码
--MyGengerric 注意后面要加括号
--CS.XluaPro.MyGengerric():ExtGetMax(888,66)  XluaPro是自定义的命名空间
local maxNum=CS.MyGengerric():ExtGetMax(888,66)  
print("[在lua中扩展方法调用] maxNum="..maxNum)

Lua要调用c#的内容

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


//定义结构体(建议结构体成员为小写)
public struct MyStruct
{
    public string x;
    public string y;
}


//定义接口
//有标记的基本上都要生成代码,搭建c#和Lua沟通的桥梁
[XLua.CSharpCallLua]
public interface MyInterface
{
    int x { get; set; }
    int y { get; set; }
    void Speak();
}

//定义委托
[XLua.CSharpCallLua]
public delegate void MyDelegate(int num);

public class IsInvokedClass : IsInvoked_FatherClass
{

    public string ChildClassName = "子类字段";


    public IsInvokedClass()
    {
        Debug.Log("IsInvokedClass 子类构造函数");
    }

    public void Mehtod1()
    {
        Debug.Log("IsInvokedClass.cs/Mehtod1 方法");
    }

    /*  定义方法重载  */

    public void Method2(int num1, int num2)
    {
        Debug.Log(GetType() + "/Method2()/ 重载方法/int浮点型/num1=" + num1 + " num2=" + num2);
    }

    public void Method2(float num1, float num2)
    {
        Debug.Log(GetType() + "/Method2()/ 重载方法/float浮点型/num1=" + num1 + " num2=" + num2);
    }

    public void Method2(string str1, string str2)
    {
        Debug.Log(GetType() + "/Method2()/ 重载方法/字符串类型/str1=" + str1 + " str2=" + str2);
    }



    //定义带有返回数值,有参数的方法,且有params 关键字
    public int Method3(int num1, int num2, params string[] strArray)
    {
        Debug.Log(GetType() + "/Method3()/ 带有params关键字的方法/");
        foreach (string item in strArray)
        {
            Debug.Log("输入的字符串内容:" + item);
        }
        return num1 + num2;
    }

    //带有结构体参数的方法
    public void Method4(MyStruct p)
    {
        Debug.Log("测试lua调用结构体方法");
        Debug.Log("p.x=" + p.x);
        Debug.Log("p.y=" + p.y);
    }

    //方法具有接口为参数的
    public void Method5(MyInterface p)
    {
        Debug.Log("测试lua调用具有接口为参数的方法");
        Debug.Log("p.x=" + p.x);
        Debug.Log("p.y=" + p.y);
        p.Speak();
    }

    //方法具有委托为参数
    public void Method6(MyDelegate p)
    {
        Debug.Log(GetType() + "/Method6()/委托参数:");
        //调用
        p.Invoke(88);
    }

    //定义一个具有多返回数值的方法
    public int Method7(int num1, out int num2, ref int num3)
    {
        Debug.Log(GetType() + "/Method7()/测试lua接收C#的多返回数值");
        num2 = 3000;
        num3 = 999;
        return num1 + 100;
    }

    //定义一个具有泛型方法为参数的。
    public void Method8(List strArray)
    {
        Debug.Log(GetType() + "/Method8()/这是一个具有泛型方法为参数的方法");
        foreach (string item in strArray)
        {
            Debug.Log("泛型集合中的内容=" + item);
        }
    }

    //C#方法中,调用我们自定义的泛型方法
    public void Method_InvokeGenger()
    {
        int maxNum = 0;
        int num1 = 100;
        int num2 = 200;

        MyGengerric obj = new MyGengerric();
        maxNum = obj.GetMax(num1, num2);
        Debug.Log("C#中比较两个数字大小: "+maxNum);

        //测试字符串的比较
        //字符串的比较是比较第一个字符
      //  string maxStr = string.Empty;
       // string str1 = "xd";
      // string str2 = "kb";

      //  MyGengerric obj = new MyGengerric();
      //  maxStr = obj.GetMax(str1, str2);
     //   Debug.Log("C#中比较两个字符串大小: " + maxStr);

    }

    //在C#中学习调用C#的扩展方法
    public void Test8_InvokeExtensionMethod()
    {
        int maxNum = 0;
        int num1 = 800;
        int num2 = 200;

        MyGengerric obj = new MyGengerric();
        //通过扩展方法来调用泛型方法
        maxNum = obj.ExtGetMax(num1, num2);
        Debug.Log("[应用扩展方法] C#中得到最大数值=" + maxNum);
    }



}

 

泛型方法的定义

/***
 *          自定义泛型类
 */
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;


   [XLua.LuaCallCSharp]
	public class MyGengerric
	{
        public T GetMax(T num1, T num2) where T : IComparable
        {
            if (num1.CompareTo(num2)<0)
            {
                return num2;
            }
            else {
                return num1;
            }
        }

		
	}



 

拓展MyGengerric的方法

 

/***
 *
 *          本类是一个“扩展方法”。
 *          
 *          本类的功能是扩展原有“MyGengerric”类的功能。
 *
 *   Description:
 *          注意:
 *             扩展方法有两大注意事项:
 *             A: 扩展方法类,必须是静态类。
 *             B: 定义的扩展方法的参数,第一个参数必须是this ,然后跟需要扩展的类名称全称。
 *
 *
 */
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


    [XLua.LuaCallCSharp]
    public static class Extension_MyGengerric
	{
    /// 
    /// 定义扩展方法,对类MyGengerric扩展一个方法
    /// 
    /// 
    /// 
    /// 
    /// 
     public static int ExtGetMax(this MyGengerric gen, int num1, int num2)
     {
            if (num1

Lua对其他的调用

1 枚举类型的调用

枚举值就像枚举类型下的静态属性一样。
testobj:EnumTestFunc(CS.Tutorial.TestEnum.E1)
上面的EnumTestFunc函数参数是Tutorial.TestEnum类型的


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

delegate 属性可以用一个luaFunction 来赋值。
c#代码里, testobj里头有个事件定义是这样:public event Action TestEvent;
在Lua内 
增加事件回调
testobj:TestEvent('+', lua_event_callback)
移除事件回调
testobj:TestEvent('-', lua_event_callback)
--------
event使用
Eg:
public event Action TestEvent;
增加事件回调:
testObj: TestEvent('+',lua_event_callback)
移除事件回调:
testObj: TestEvent('-',lua_event_callback)


Lua调用C#经验总结


一: lua 调用C#,需要在Xlua中生成“适配代码”,则在这个类打入一个
[luaCallCSharp] 的标签


二: 如果lua调用C#的系统API ,则无法拿到源代码,无法打入标签。则在配置文件(ExampleGenConfig.cs)
使用“静态列表”方式解决。
Eg:
public static List mymodule_LuaCallCS_List=new
List()
{
typeof(GameObject),
typeof(Dictionary),
};
然后把以上代码放入一个静态类中即可。

三: 实际开发过程中,lua 调用C# 用的比较多。
xlua 的优点体现的没有必要每次改的时候,都要生成代码。主要原理是
依赖于编译器环境下,利用反射来动态生成代码接口。
四: 在标有“[XLua.LuaCallCSharp]”的C#类中,添加新的方法后,如
果是生成了代码类,则必须重新生成或者删除,否则Xlua 用以前生成的,
进行注册查询,会出现lua 异常:“试图访问一个nil 的方法”
 

 

你可能感兴趣的:(unity)