01.操作符重载和函数重载
C#中定义的操作符重载和函数重载在Lua中基本上能够使用,不过需要注意的是由于Lua中表示数值的类型只有一种(number),所以C#中对于数值类型之间的重载是不能够正确的识别的,通常只会调用类型符合的重载函数列表中先定义的函数
[LuaCallCSharp]
public class Overload
{
public int Add(int num1, int num2)
{
Debug.Log("Add-int");
return num1 + num2;
}
public float Add(float num1, float num2)
{
Debug.Log("Add-float");
return num1 + num2;
}
public string Add(string num1, string num2)
{
Debug.Log("Add-string");
return num1 + num2;
}
}
local Overload=CS.Overload--获取一个类的映射
local overload=CS.Overload()--实例化一个类
print(overload:Add(1,2));
print(overload:Add(1.5,2.1));
print(overload:Add("22","22"));
由于在Lua中只有一种数值类型(number),所以参数为int和float类型的Add函数都满足要求,这个时候会调用先定义的重载函数,也就是重载为int类型的Add
当先定义参数float类型后定义int类型的Add函数时,Lua代码调用就是参数类型为float的Add函数了
02.可变参数与默认参数
在Lua中调用它们的时候,参数的规则与C#中相同
对于C#的如下方法:
void VariableParamsFunc(int a, params string[] strs)
可以在lua里头这样调用:
testobj:VariableParamsFunc(5, ‘hello’, ‘john’)
public void DefaultParam(int arg0, string arg1 = "1", int arg2 = 2)
{
Debug.Log("arg0:" + arg0);
Debug.Log("arg1:" + arg1);
Debug.Log("arg2:" + arg2);
}
public void VariableParam(int arg0, params string[] args)
{
Debug.Log("arg0:" + arg0);
Debug.Log(args.Length);
foreach (string arg in args)
{
Debug.Log(arg + " ");
}
}
local Overload=CS.Overload--获取一个类的映射
local overload=CS.Overload()--实例化一个类
overload:VariableParam(10,"1", "2", "3", "4");
overload:DefaultParam(1);
03.访问C#枚举
枚举值就像枚举类型下的静态属性一样。
testobj:EnumTestFunc(CS.Tutorial.TestEnum.E1)
上面的EnumTestFunc函数参数是Tutorial.TestEnum类型的
另外,如果枚举类加入到生成代码的话,枚举类将支持__CastFrom方法,可以实现从一个整数或者字符串到枚举值的转换,例如:
CS.Tutorial.TestEnum.__CastFrom(1)
CS.Tutorial.TestEnum.__CastFrom(‘E1’)
在Lua中有以下五种方法可以访问到枚举变量:
1当作普通的静态属性访问
2使用__CastFrom函数,从枚举值对应的数值做类型转换
3使用__CastFrom函数,从枚举值对应的字符串做类型转换
4直接传入枚举值对应的数值
5直接传入枚举值对应的字符串
[LuaCallCSharp]
public enum Language
{
C_PLUS_PLUS,
C_SHARP
}
[LuaCallCSharp]
public class EnumParam
{
public void PrintEnum(Language language)
{
switch(language){
case Language.C_PLUS_PLUS:
Debug.Log("C++");
break;
case Language.C_SHARP:
Debug.Log("C#");
break;
}
}
}
--访问枚举
local enumParam=CS.EnumParam();
local Language=CS.Language;
--当作普通的静态属性访问
enumParam:PrintEnum(Language.C_PLUS_PLUS);
--直接传入枚举值对应的字符串
enumParam:PrintEnum("C_SHARP")
--直接传入枚举值对应的数值
enumParam:PrintEnum(1);
--使用__CastFrom函数,从枚举值对应的数值做类型转换
enumParam:PrintEnum(Language.__CastFrom("C_PLUS_PLUS"));
--使用__CastFrom函数,从枚举值对应的数值做类型转换
enumParam:PrintEnum(Language.__CastFrom(1));
04.
访问C#委托
delegate使用(调用,+,-)
C#的delegate调用:和调用普通lua函数一样
+操作符:对应C#的+操作符,把两个调用串成一个调用链,右操作数可以是同类型的C# delegate或者是lua函数。
-操作符:和+相反,把一个delegate从调用链中移除。
Ps:delegate属性可以用一个luafunction来赋值。
[LuaCallCSharp]
class DelegateClass
{
public delegate void ActionString(string arg);
public ActionString action = (arg) =>
{
Debug.Log("action:" + arg);
};
public ActionString actionString1 = (arg) =>
{
Debug.Log("actionString1:" + arg);
};
public ActionString actionString2 = (arg) =>
{
Debug.Log("actionString2:" + arg);
};
}
--访问委托
local delegateClass=CS.DelegateClass();
--使用delegateClass类的对象访问委托变量action
local action1=delegateClass.action;
action1("hi-1");
--由于在Lua中没有"+="和"-="操作符,在增加委托链的时候只能使用"+"和"-"操作符
action1=action1+delegateClass.actionString1+delegateClass.actionString2;
action1("hi-2");
action1=action1-delegateClass.actionString2;
action1("hi-3");
在使用Lua代码访问C#委托时需要注意,访问委托类型的方式与访问静态变量的方式相同,访问(静态/非静态)委托的变量的方式与访问(静态/非静态)成员变量的方式相同
--使用DelegateClass类访问委托类型ActionString,
--定义一个ActionString类型的委托变量action2
local DelegateClass=CS.DelegateClass;
local delegateClass=CS.DelegateClass();
---此时action2的值为nil
local action2=DelegateClass.ActionString;
action2=delegateClass.actionString1;
action2("hi-4");
action2=action2+delegateClass.actionString2;
action2("hi-5");
05.访问C#事件
比如testobj里头有个事件定义是这样:public event Action TestEvent;
增加事件回调
testobj:TestEvent(’+’, lua_event_callback)
移除事件回调
testobj:TestEvent(’-’, lua_event_callback)
在访问C#事件的时候需要生成代码,所以必须要为事件的委托类型加上一个Attribute:[CSharpCallLua],关于为什么这里需要加[CSharpCallLua]而不是[LuaCallCSharp],在xLua的github主页的FAQ上作者是这么解释的:
LuaCallCSharp以及CSharpCallLua两种生成各在什么场景下用?
看调用者和被调用者,比如要在lua调用C#的GameObject.Find函数,或者调用gameobject的实例方法,属性等,GameObject类要加LuaCallSharp,而想把一个lua函数挂到UI回调,这是调用者是C#,被调用的是一个lua函数,所以回调声明的delegate要加CSharpCallLua。
有时会比较迷惑人,比如List.Find(Predicate match)的调用,List当然是加LuaCallSharp,而Predicate却要加CSharpCallLua,因为match的调用者在C#,被调用的是一个lua函数。
更无脑一点的方式是看到“This delegate/interface must add to CSharpCallLua : XXX”,就把XXX加到CSharpCallLua即可。
[LuaCallCSharp]
class EventClass
{
//在访问C#事件的时候需要生成代码
//所以必须要为事件的委托类型加上一个Attribute:[CSharpCallLua],
[CSharpCallLua]
public delegate void EventAction();
public event EventAction Events;
public EventAction action1 = () =>
{
Debug.Log("action1");
};
public EventAction action2 = () =>
{
Debug.Log("action2");
};
public void TriggerEvent()
{
Events();
}
}
在添加事件的时候,既可以使用C#中的委托变量,也可以使用Lua中的函数
同时在添加和移除事件的时候应该使用以下的方式
object:event("+", delegate)
object:event("-", delegate)
function lua_action()
print("lua_action:")
end
local eventClass=CS.EventClass();
eventClass:Events("+",lua_action);
eventClass:Events("+",eventClass.action1);
eventClass:Events("+",eventClass.action2);
eventClass:TriggerEvent();