上一篇講到了通過接口的形式,可以訪問表內部的函數,那如果這個方法是一個全局的函數,就是這篇博客要講解的。
先上Lua中的代碼。
function TestOne()
print('no parm')
end
function TestTwo(a,b)
print(a,b)
end
function TestThree(a,b)
return a+b
end
function TestFour(a,b)
return a+b,a,b
end
上面有四個函數,分別爲沒有參數,帶參數,有返回值,有多個返回值這4種情況。
還是用LuaEnv.Global.Get<T>方法來實現。Lua中對應的函數,可以通過C#種的事件Action和委託delegate來實現。
1.無參數的調用
LuaEnv env = new LuaEnv();
env.DoString("require 'CSharpCallLua' ");
Action ac1=env.Global.Get<Action>("TestOne");
ac1();
2.帶參數的調用
接下來的幾種,都需要在方法前加上 [CSharpCallLua],如果不加的話,會報如下錯誤。
稍後再分析[CSharpCallLua]這句話到底起什麼樣的一個作用。
這裏不能再用Action去接收。而需要去委託,具體什麼原因還真不敢下結論。個人感覺[CSharpCallLua]定義的,是一個類型。比如上一篇博客說到的接口類,和現在用委託自定義的一種類型。先上錯誤的寫法。
[CSharpCallLua]
private Action<int, int> ac1;
ac1 = env.Global.Get<Action<int, int>>("TestTwo");
再上正確的寫法
[CSharpCallLua]
delegate void AC2(int a,int b);
AC2 ac2 = env.Global.Get<AC2>("TestTwo");
ac2(2,5);
3.帶返回值的調用
和上面委託就沒啥區別了,也是上一個正確寫法和錯誤寫法
錯誤寫法
[CSharpCallLua]
private Func<int, int, int> ac3;
int res=ac3(2,5);
這裏Func的用法如果不會就去自行解決好了。
正確寫法
[CSharpCallLua]
delegate int AC3(int a, int b);
AC3 ac3= env.Global.Get<AC3>("compare");
int v = ac3(2, 3);
4.帶多個返回值的調用
Lua中支持多個返回值的回調,但C#沒這麼一說。這時候就可以在上面帶一個返回值的寫法基礎上通過ref,out形式獲取別的返回值。
[CSharpCallLua]
delegate int AC4(int a, int b,out int c,out int d);
AC4 ac4=env.Global.Get<AC4>("TestFour");
int res1;
int res2;
ac4(2,3,out res1,out re2);
當然這裏也可以用ref來實現,就不說了。
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
接下來寫兩個過程中發現的需要注意的問題
1.在調用LuaEnv.Dispose()之前,要把所有訪問過程中生成的函數置爲空,否則會報無法釋放的錯誤。
需要加入ac1=null之後再去釋放。
2.就是 [CSharpCallLua]這個到底起的什麼作用了,在我研究過程中發現,比如上述2帶參數的調用。
我直接通過錯誤寫法,下面簡稱T1
Action<int, int> ac1 = env.Global.Get<Action<int, int>>("TestTwo");
是不行的,但是!!!如果我上面寫了正確方法:簡稱T2
[CSharpCallLua]
delegate void AC2(int a,int b);
而我並不去通過AC2去生成新的方法實例,只是把它寫那兒,然後再通過T1寫法去寫代碼,竟然是可以走通的。
剛開始懷疑是在在類初始化時做的手腳。我把T1放在了Awake裏,還是可以走通的。個人感覺,問題出在委託delegate 本身和Action之間的關係。Action和Func,本來就屬於U3D對delegate委託的一種封裝,所以當本身將T2前加了[CSharpCallLua]的時候,它就等同於給Action<int,int>類型的方法加上了[CSharpCallLua]。好吧,我也只能說個人猜測了,原理到底是啥,我不敢下結論,如果有大神看到這裏,也可以幫我分析解決下,個人覺得後者可能性非常大。
這塊兒爲什麼對於帶參數的委託需要自定義,而不能用Action和Func暫時還不太清楚。也希望看到的朋友能幫忙解釋一下。
5.通過Luafunction調用方法
它的參數,以及返回值都是object[]類型的,可以傳遞很多個。但和上面委託的方式相比,缺點就在於運行消耗較大,有點在於不需要像上面那樣自己定義。不過貌似XLUA不建議我們用這個。
LuaFunction lf = env.Global.Get<LuaFunction>("compare1");
lf.Call();
引用文檔裏的話,如果lua的實現的部分都以delegate和interface的方式提供,使用方可以完全和xLua解耦:由一個專門的模塊負責xlua的初始化以及delegate、interface的映射,然後把這些delegate和interface設置到要用到它們的地方。也就是表,建議用映射,方法,建議用delegate.