toLua[四] Examples 03_CallLuaFunction分析

一.运行工程

本例展示如何用C#调用Lua函数,运行表现很简单,打印几行文本,我们关注打印的最后4行

二.代码分析

2.1 代码展示

cs 复制代码
using UnityEngine;
using System.Collections;
using LuaInterface;
using System;

public class CallLuaFunction : MonoBehaviour 
{
    private string script =
        @"  function luaFunc(num)                        
                return num + 1
            end

            test = {}
            test.luaFunc = luaFunc
        ";

    LuaFunction luaFunc = null;
    LuaState lua = null;
    string tips = null;
	
	void Start () 
    {
#if UNITY_5 || UNITY_2017 || UNITY_2018
        Application.logMessageReceived += ShowTips;
#else
        Application.RegisterLogCallback(ShowTips);
#endif
        new LuaResLoader();
        lua = new LuaState();
        lua.Start();
        DelegateFactory.Init();        
        lua.DoString(script);

        //Get the function object
        luaFunc = lua.GetFunction("test.luaFunc");

        if (luaFunc != null)
        {
            int num = luaFunc.Invoke<int, int>(123456);
            Debugger.Log("generic call return: {0}", num);

            num = CallFunc();
            Debugger.Log("expansion call return: {0}", num);

            Func<int, int> Func = luaFunc.ToDelegate<Func<int, int>>();
            num = Func(123456);
            Debugger.Log("Delegate call return: {0}", num);
            
            num = lua.Invoke<int, int>("test.luaFunc", 123456, true);
            Debugger.Log("luastate call return: {0}", num);
        }

        lua.CheckTop();
	}

    void ShowTips(string msg, string stackTrace, LogType type)
    {
        tips += msg;
        tips += "\r\n";
    }

#if !TEST_GC
    void OnGUI()
    {
        GUI.Label(new Rect(Screen.width / 2 - 200, Screen.height / 2 - 150, 400, 300), tips);
    }
#endif

    void OnDestroy()
    {
        if (luaFunc != null)
        {
            luaFunc.Dispose();
            luaFunc = null;
        }

        lua.Dispose();
        lua = null;

#if UNITY_5 || UNITY_2017 || UNITY_2018
        Application.logMessageReceived -= ShowTips;
#else
        Application.RegisterLogCallback(null);
#endif
    }

    int CallFunc()
    {        
        luaFunc.BeginPCall();                
        luaFunc.Push(123456);
        luaFunc.PCall();        
        int num = (int)luaFunc.CheckNumber();
        luaFunc.EndPCall();
        return num;                
    }
}

2.2 ToLua 部分API用法

下面给出README(LuaFramework\ToLua\Examples\README.md)文档中的解释

tolua# 简化了lua函数的操作,通过LuaFunction封装(并缓存)一个lua函数,并提供各种操作, 建议频繁调用函数使用无GC方式。<br>

* LuaState.GetLuaFunction 获取并缓存一个lua函数, 此函数支持串式操作, 如"test.luaFunc"代表test表中的luaFunc函数。<br>

* LuaState.Invoke 临时调用一个lua function并返回一个值,这个操作并不缓存lua function,适合频率非常低的函数调用。<br>

* LuaFunction.Call() 不需要返回值的函数调用操作<br>

* LuaFunction.Invoke() 有一个返回值的函数调用操作 <br>

* LuaFunction.BeginPCall() 开始函数调用 <br>

* LuaFunction.Push() 压入函数调用需要的参数,通过众多的重载函数来解决参数转换gc问题 <br>

* LuaFunction.PCall() 调用lua函数 <br>

* LuaFunction.CheckNumber() 提取函数返回值, 并检查返回值为lua number类型 <br>

* LuaFunction.EndPCall() 结束lua函数调用, 清楚函数调用造成的堆栈变化 <br>

* LuaFunction.Dispose() 释放LuaFunction, 递减引用计数,如果引用计数为0, 则从_R表删除该函数 <br>

> **注意:** 无论Call还是PCall只相当于lua中的函数'.'调用。<br>

请注意':'这种语法糖 self:call(...) == self.call(self, ...) <br>

c# 中需要按后面方式调用, 即必须主动传入第一个参数self <br>

2.3 调用Lua写法分析

首先我们将代码进行整理,可以看出有如下4种调用Lua函数的做法

cs 复制代码
    LuaState lua = new LuaState();
    lua.Start();
    LuaFunction luaFunc = lua.GetFunction("test.luaFunc");
    //style1
    int num = luaFunc.Invoke<int, int>(123456);
    Debugger.Log("generic call return: {0}", num);
    //style2
    num = CallFunc();
    Debugger.Log("expansion call return: {0}", num);
    //style3
    Func<int, int> Func = luaFunc.ToDelegate<Func<int, int>>();
    num = Func(123456);
    Debugger.Log("Delegate call return: {0}", num);
    //style4
    num = lua.Invoke<int, int>("test.luaFunc", 123456, true);
    Debugger.Log("luastate call return: {0}", num);

    int CallFunc()
    {        
        luaFunc.BeginPCall();                
        luaFunc.Push(123456);
        luaFunc.PCall();        
        int num = (int)luaFunc.CheckNumber();
        luaFunc.EndPCall();
        return num;                
    }

先分析style1,在Invoke按F12跳转

  • 可以看到Invoke是泛型方法,内部的调用和style2的做法本质上是一样的;
  • 根据要调用方法的参数类型和数量,选择不同的泛型方法

style2和style1本质一样,使用style1简化的写法即可

style3是委托式写法,应该和style1也是相同的

style4使用的是LuaState的Invoke方法,看上去和style1很像,但是README里说style4适合低频率调用的情况,因此谨慎使用

三.C#调用Lua方法小结

step1:通过LuaState.GetFunction获取LuaFunction对象

step2:通过Luafunction.Invoke泛型方法,调用Lua函数

cs 复制代码
        private string script =
        @"  function luaFunc(num)                        
                return num + 1
            end

            test = {}
            test.luaFunc = luaFunc
        ";
        //step1:获取LuaFunction对象
        LuaFunction luaFunc = lua.GetFunction("test.luaFunc");
        if (luaFunc != null)
        {
            //step2:调用Invoke方法
            int num = luaFunc.Invoke<int, int>(123);
            Debugger.Log("generic call return: {0}", num);
        }
相关推荐
大Mod_abfun7 小时前
Unity游戏基础-4(人物移动、相机移动、UI事件处理 代码详解)
游戏·ui·unity·游戏引擎
大Mod_abfun10 小时前
Unity游戏基础-3(UI层)
游戏·ui·unity·游戏引擎
ellis197010 小时前
toLua[五] Examples 04_AccessingLuaVariables分析
unity
大有数据可视化17 小时前
告别传统监控:基于Unity+IoT打造沉浸式数字孪生车间
物联网·unity·游戏引擎
雪下的新火20 小时前
爆炸特效:Unity+Blender-02-火焰
unity·游戏引擎·blender·特效制作·笔记分享
雪下的新火20 小时前
Unity+Blender-03-输出制作Flipbook
游戏·unity·游戏引擎·blender·资源·笔记分享
大Mod_abfun1 天前
Unity游戏基础-1(安装~工作区构建)
游戏·unity·游戏引擎·大学课程·数媒
EQ-雪梨蛋花汤1 天前
【Unity笔记】Unity XR 模式下 Point Light 不生效的原因与解决方法
笔记·unity·xr
希望PZM1 天前
Unity实现UV的中心缩放
unity·游戏引擎·uv