UH2S3L6——全局函数获取

本章代码关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
LuaFuntion                        //可用于装载Lua函数的类
luaState.GetFunction() //通过lua解析器获取全局函数
luaFunction.Call<>() //调用Lua的无返回值的函数,适用于不多于9个参数的无返回值的Lua函数
luaFunction.ToDelegate<>() //将lua函数类提取到委托中
lunFunction.Dispose() //销毁lua函数,防止内存泄露
luaFunction.BeginPCall() //开始调用lua函数
luaFunction.Push() //传入参数
luaFunction.PCall() //结束参数的传入,调用函数
luaFunction.CheckNumber() //获取Number类型的返回值,对于其他类型的返回值需要使用不同名称的Check函数
luaFunction.CheckBoolean() //获取Boolean类型的返回值
luaFunction.CheckString() //获取String类型的返回值
luaFunction.EndPCall() //结束调用lua函数
luaFunction.Invoke<>() //快速调用有参有返回值lua函数,最后的泛型参数为返回值类型,其他为参数类型,适用于不多于6个参数的有返回值Lua函数
luaState.Invoke<>() //直接通过解析器调用lua函数,最后的泛型参数为返回值类型,其他为参数类型,适用于不多于6个参数的有返回值Lua函数

全局函数的获取

无参无返回值函数

假设要调用下面的lua函数

1
2
3
4
-- 无参无返回函数
testFun = function()
print("无参无返回值")
end

调用无参无返回值Lua函数有三种方式:

  1. 通过解析器中的GetFunction()​方法

    1
    2
    3
    LuaFunction function = LuaManager.Instance.LuaState.GetFunction("testFun");
    function.Call();
    function.Dispose();
  2. 通过中括号名字再as​得到LuaFunction

    1
    2
    3
    function = LuaManager.Instance.LuaState["testFun"] as LuaFunction;
    function.Call();
    function.Dispose();
  3. 可以得到LuaFunction​后再提取到委托中

    1
    2
    3
    function = LuaManager.Instance.LuaState.GetFunction("testFun");
    UnityAction action = function.ToDelegate<UnityAction>();
    action.Invoke();

销毁LuaFunction

如果LuaFunction​内的函数使用完毕了,记得执行Dispose()​方法,否则会持续占用内存

1
2
3
LuaFunction function = LuaManager.Instance.LuaState.GetFunction("testFun");
function.Call();
function.Dispose();

image

ToLua使用委托初始化

注意!如果要让委托使用LuaFunction​的内容,必须要执行DelegateFactory.Init()​来初始化委托的使用!!!

1
2
3
luaState = new LuaState();
luaState.Start();
DelegateFactory.Init(); //委托初始化相关

有参有返回值函数

假设要调用下面的lua函数

1
2
3
4
5
-- 有参有返回函数
testFun2 = function(a)
print("有参有返回值")
return a + 100
end

调用Lua有参有返回值函数有四种方式:

  1. 逐步执行各个Call​方法

    需要依次执行BeginPCall()​​,Push()​​,PCall()​​,Checkxxx()​​,EndPCall()​​方法
    Lua函数参数有多少,就要执行多少次Push()​​方法,适用于任意数量的有返回值Lua函数
    Checkxxx()​​用于获取返回值,后面的名称决定获取什么类型的值
    CheckNumber()​​就会获取Lua中的Number​​类型的返回值,在C#中会返回一个double​​类型的值

    1
    2
    3
    4
    5
    6
    7
    luaFunction = LuaManager.Instance.LuaState.GetFunction("testFun2");
    luaFunction.BeginPCall(); //开始使用
    luaFunction.Push(99); //传参
    luaFunction.PCall(); //传参结束,调用
    int result = (int)luaFunction.CheckNumber(); //得到返回值
    luaFunction.EndPCall(); //执行结束
    print("有参有返回值 Call: " + result);

    image

  2. 使用封装好的Invoke​方法

    LuaFunction​​内部会将用到的各个Call​​方法封装好,外部通过泛型直接调用即可,
    最后一个泛型代表的是返回值类型,前面的都是参数的类型
    LuaFunction​​内封装的Invoke​​方法重载可以用于不多于6个参数的有返回值Lua函数

    1
    2
    result = luaFunction.Invoke<int, int>(199);
    print("有参有返回值 Invoke: " + result);

    image

  3. 提取到委托中

    可以使用系统声明好的委托Func<>​​来承接,最后一个泛型同样是指代返回值类型

    1
    2
    3
    Func<int, int> func = luaFunction.ToDelegate<Func<int, int>>();
    result = func(900);
    print("有参有返回值 委托: " + result);

    image

  4. 使用解析器直接Invoke​,类似第二种方法

    如果lua函数是全局的,可以直接通过解析器去调用函数
    最后一个泛型代表的是返回值类型,前面的都是参数的类型
    第一个参数要传入函数名,中间传入Lua函数的参数
    最后一个参数是如果函数调用出错是否报错,默认为true​​即可

    1
    2
    result = LuaManager.Instance.LuaState.Invoke<int, int>("testFun2", 800, true);
    print("有参有返回值 luaState直接调用: " + result);

    image

多返回值函数

假设要调用下面的lua函数

1
2
3
4
5
-- 多返回值函数
testFun3 = function(a)
print("多返回值")
return 1, 2, false, "123", a
end

调用Lua多返回值函数有两种方式:

  1. 逐步执行各个Call​方法

    需要依次执行BeginPCall()​​,Push()​​,PCall()​​,Checkxxx()​​,EndPCall()​​方法
    Lua函数返回值有多少,就要执行多少次Checkxxx()​​方法,Checkxxx()​​用于获取返回值,后面的名称决定获取什么类型的值
    CheckNumber()​​就会获取Lua中的Number​​类型的返回值,在C#中会返回一个double​​类型的值
    CheckBoolean()​​就会获取Lua中的Boolean​​类型的返回值,在C#中会返回一个bool​​类型的值
    CheckString()​​就会获取Lua中的String​​类型的返回值,在C#中会返回一个string​​类型的值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    luaFunction = LuaManager.Instance.LuaState.GetFunction("testFun3");
    luaFunction.BeginPCall();
    luaFunction.Push(1000);
    luaFunction.PCall();
    int a1 = (int)luaFunction.CheckNumber();
    int b1 = (int)luaFunction.CheckNumber();
    bool c1 = luaFunction.CheckBoolean();
    string d1 = luaFunction.CheckString();
    int e1 = (int)luaFunction.CheckNumber();
    luaFunction.EndPCall();
    print($"多返回值 Call: {a1}, {b1}, {c1}, {d1}, {e1}");

    image

  2. 使用带out​参数的自定义委托

    我们可以使用带out​​参数的自定义委托来承接多返回值的函数,
    第一个返回值还是以C#委托的返回值获取,其余返回值通过传入的out参数承接

    1
    public delegate int CustomCallOut(int a, out int b, out bool c, out string d, out int e);

    注意!对于自定义委托,如果要让其能够使用toLua的Lua函数,必须要进行注册操作

    然后就可以将函数提取到委托里,执行委托,通过返回值和传入到out参数中的变量获取所有返回值(这里使用了out内联声明​)

    1
    2
    3
    CustomCallOut callOut = luaFunction.ToDelegate<CustomCallOut>();
    result = callOut(999, out int b2, out bool c2, out string d2, out int e2);
    print($"多返回值 委托: {result}, {b2}, {c2}, {d2}, {e2}");

    image

自定义委托在toLua注册

和xLua需要在自定义委托前加上特定特性并生成代码一样,toLua使用自定义委托也需要进行类似的操作

例如我们要让toLua可以使用下面的委托:

1
public delegate int CustomCallOut(int a, out int b, out bool c, out string d, out int e);

我们需要先在CustomSettings.cs的customDelegateList​中写入_DT(typeof(自定义委托名))

1
2
3
4
5
6
7
8
9
10
11
public static class CustomSettings
{
//...
//附加导出委托类型(在导出委托时, customTypeList 中牵扯的委托类型都会导出, 无需写在这里)
public static DelegateType[] customDelegateList =
{
//...
_DT(typeof(CustomCallOut)),
};
//...
}

然后,点击工具栏的Lua - Generate All,重新生成代码

image

变长函数

假设要调用下面的lua函数

1
2
3
4
5
6
7
8
9
-- 变长参数函数
testFun4 = function(a, ...)
print("变长参数")
print(a)
arg = {...}
for key, value in pairs(arg) do
print(key, value)
end
end
  1. 使用带变长参数的自定义委托

    我们可以使用带变长参数的自定义委托来承接带变长参数的lua函数,直接在参数列表声明变长参数即可

    1
    public delegate void CustomCallParams(int a, params object[] objs);

    注意!对于自定义委托,如果要让其能够使用toLua的Lua函数,必须要进行注册操作

    然后就可以将函数提取到委托里,执行委托,通过返回值和传入到out参数中的变量获取所有返回值

    1
    2
    3
    luaFunction = LuaManager.Instance.LuaState.GetFunction("testFun4");
    CustomCallParams callParams = luaFunction.ToDelegate<CustomCallParams>();
    callParams(100, 1, true, "123", 0, false);
  2. 使用Call​方法

    针对无返回值的Lua函数,我们可以直接使用call​函数去调用它,泛型决定参数类型,最多传入9个参数(包括定长参数和变长参数函数)

    1
    luaFunction.Call<int, int, bool, string, int>(100, 10, true, "123", 0);