zoukankan      html  css  js  c++  java
  • Lua基本语法-lua与C#的交互(相当简单详细的例子)

    lua脚本 与 C#的交互


    本文提供全流程,中文翻译。

    Chinar坚持将简单的生活方式,带给世人!

    (拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例)




    1

    Lua And C# —— Lua 和 C#的交互准备工作


    早期 Lua C# 之间的交互,需要用Lua官方做好的接口 LuaInterface.dll 等文件来实现


    文件的下载直接跳转Lua官方网站:LuaInterface完成下载

    点击 luainterface 链接 ↓↓

    这里写图片描述

    点击 1.5.3 链接 开始下载

    这里写图片描述

    下载完成后解压压缩文件,并打开 Built 文件夹

    目录中的3个文件: lua51.dll LuaInterface.dll luanet.dll 是暂时需要用到的

    这里写图片描述

    打开VS,创建一个控制台脚本

    这里写图片描述

    将下载好的 LuaInterface.dll 文件拖到项目中

    并按照步骤添加引用

    图中我没有 using LuaInterface; 请自己添加上

    这里写图片描述

    找到项目中的目录,并将下载好的 lua51.dll luanet.dll 两个文件,拷贝到DeBug文件目录中

    这里写图片描述


    2

    C# Create Lua —— 用C#在lua环境中编写lua


    用简单的控制台程序 测试,输出

    举个栗子黑白88

    using System;
    using LuaInterface; //引用命名空间
    
    
    namespace ChinarTest
    {
        /// <summary>
        /// 测试类
        /// </summary>
        class Program
        {
            static void Main(string[] args) 
            {
                Lua lua    = new Lua();        //创建一个lua解释器
                lua["num"] = 66;               //用C#脚本在lua环境中,创建一个变量
                lua["str"] = "chinar";         //用C#脚本在lua环境中,创建一个字符串变量
                Console.WriteLine(lua["num"]); //输出
                Console.WriteLine(lua["str"]); //输出
                Console.ReadKey();             //等待输入
            }
        }
    }

    输出结果:

    66
    chinar

    3

    lua.DoString —— 在C#脚本中编写Lua脚本


    lua.DoString() 用于创建代码段

    举个栗子黑白88

    using System;
    using LuaInterface; //引用命名空间
    
    
    namespace ChinarTest
    {
        /// <summary>
        /// 测试类
        /// </summary>
        class Program
        {
            static void Main(string[] args)
            {
                Lua lua = new Lua();                              //创建一个lua解释器
                lua.DoString("num=666");                          //用C#脚本在lua环境中,创建一段lua脚本:num=666
                lua.DoString("str='chianr666'");                  //用C#脚本在lua环境中,创建一段lua脚本:str='chianr666'
                object[] values = lua.DoString("return num,str"); //用一个object数组 去接受返回值
                foreach (var value in values)                     //遍历 values 数组中的元素
                {
                    Console.WriteLine(value); //输出
                }
    
                Console.ReadKey(); //等待输入
            }
        }
    }

    输出结果:

    666
    chianr666

    4

    lua.DoFile —— 用C#加载Lua脚本文件


    lua.DoFile() 用于找到目录中的Lua文件,并加载

    需要将写好的Lua文件拖到项目中,并且修改属性为 :如果较新则复制 / 始终复制

    否则会出现找不到文件的 报错信息

    不会的请看下图

    这里写图片描述

    举个栗子黑白88

    using System;
    using LuaInterface; //引用命名空间
    
    
    namespace ChinarTest
    {
        /// <summary>
        /// 测试类
        /// </summary>
        class Program
        {
            static void Main(string[] args)
            {
                Lua lua = new Lua();      //创建一个lua解释器
                lua.DoFile("Chinar.lua"); //加载lua文件 —— lua.DoFile(文件名)
                Console.ReadKey();        //等待输入
            }
        }
    }

    下边是 Chinar.lua 文件

    print('I am Chianr')
    MyTable={1,22,333,4444,55555,666666}
    print(table.concat(MyTable)..'I am Chianr')

    输出结果:

    I am Chianr
    122333444455555666666I am Chianr

    5

    lua.RegisterFunction —— 将C#中的函数/方法 写入到Lua脚本中


    lua.RegisterFunction() 用于将C#中的函数/方法 写入到Lua脚本中

    注册方法
    lua.RegisterFunction (注册到Lua中以后方法的名称,程序对象,程序的类型program.GetType().(传入C#中的方法名:需要是公有方法))

    注册静态方法
    lua.RegisterFunction (注册到Lua中以后方法的名称,空,程序的类型 typeof(Program).(传入C#中的方法名:需要是公有方法))

    注册的方法必须是 public ,否则会找不到

    举个栗子黑白88

    using System;
    using LuaInterface; //引用命名空间
    
    
    namespace ChinarTest
    {
        /// <summary>
        /// 测试类
        /// </summary>
        class Program
        {
            static void Main(string[] args)
            {
                Lua     lua     = new Lua();     //创建一个lua解释器
                Program program = new Program(); //声明一个对象
    
                //lua.RegisterFunction 注册方法(注册到Lua中以后方法的名称,程序对象,程序的类型program.GetType().(传入C#中的方法名:需要是公有方法))
                lua.RegisterFunction("LuaChinarTest", program, program.GetType().GetMethod("ChinarTest"));
                //然后用lua.DoString(Lua中方法名())调用测试
                lua.DoString("LuaChinarTest()");
    
                //lua.RegisterFunction 注册静态方法(注册到Lua中以后方法的名称,空,程序的类型 typeof(Program).(传入C#中的方法名:需要是公有方法))
                lua.RegisterFunction("LuaChinarStaticTest", null, typeof(Program).GetMethod("ChinarStaticTest"));
                //然后用lua.DoString(Lua中静态方法名())调用测试
                lua.DoString("LuaChinarStaticTest()");
    
                Console.ReadKey(); //等待输入
            }
    
    
            /// <summary>
            /// 一个测试方法
            /// </summary>
            public void ChinarTest()
            {
                Console.WriteLine("这是一个空方法");
            }
    
    
            /// <summary>
            /// 一个静态测试方法
            /// </summary>
            public static void ChinarStaticTest()
            {
                Console.WriteLine("这个一个静态空方法");
            }
        }
    }

    输出结果:

    这是一个空方法
    这个一个静态空方法

    6

    require —— Lua中引用C#中的类


    Lua 调用 C# 的类需要: LuaInterface.dll luanet.dll

    luanet.dll 拷贝到工程 DeBug 输出目录中

    lua 脚本中就不需要使用 package.cpath require

    这点,在第一步 配置引用信息的时候,就做过了,如果没有做的报错了。请返回第一步


    报错点1:
    require “luanet” :如果DeBug中有luanet.dll文件,则不需要在Lua脚本中再次引用

    否则会报错:
    “LuaInterface.LuaException”类型的未经处理的异常在 LuaInterface.dll 中发生,其他信息: error loading module ‘luanet’ from file ‘.luanet.dll’


    报错点2:
    另外,修改 ChinarClass.lua 的属性后,一定要保存,不然还会报错找不到文件

    举个栗子黑白88

    using System;
    using LuaInterface; //引用命名空间
    
    
    namespace ChinarTest
    {
        /// <summary>
        /// 测试类
        /// </summary>
        class Program
        {
            static void Main(string[] args)
            {
                Lua lua = new Lua();           //创建一个lua解释器
                lua.DoFile("ChinarClass.lua"); //Lua引用C#中的类
                Console.ReadKey();             //等待输入
            }
    
    
            public int    ChinarNum = 60;       //整形变量
            public string Name      = "Chinar"; //字符串变量
    
    
            /// <summary>
            /// 用来让Lua脚本测试的方法
            /// </summary>
            public void ChinarTestFun()
            {
                Console.WriteLine("你好,Chinar");
            }
    
    
            /// <summary>
            /// Ref方法,参数
            /// </summary>
            /// <param name="name"></param>
            /// <param name="count"></param>
            public void TestRef(string name, ref int count)
            {
                Console.WriteLine(name);
                Console.WriteLine(count);
                count = name.Length;
            }
    
    
            /// <summary>
            /// Out方法,参数
            /// </summary>
            /// <param name="name"></param>
            /// <param name="count"></param>
            public void TestOut(string name, out int count)
            {
                Console.WriteLine(name);
                count = name.Length;
            }
        }
    }

    输出结果:

    ProxyType(System.Int32): 46104728
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    60
    你好,Chinar
    chinar.fun
    nil     10
    chinar.fun
    8
    nil     10

    7

    All —— 全脚本数据


    整个脚本项目

    1个C#脚本 2个Lua脚本

    举个栗子黑白88

    using System;
    using LuaInterface; //引用命名空间
    
    
    namespace ChinarTest
    {
        /// <summary>
        /// 测试类
        /// </summary>
        class Program
        {
            static void Main(string[] args)
            {
                Lua lua = new Lua(); //创建一个lua解释器
    
    
                lua["num"] = 66;               //用C#脚本在lua环境中,创建一个变量
                lua["str"] = "chinar";         //用C#脚本在lua环境中,创建一个字符串变量
                Console.WriteLine(lua["num"]); //输出
                Console.WriteLine(lua["str"]); //输出
    
    
                lua.DoString("num=666");                          //用C#脚本在lua环境中,创建一段lua脚本:num=666
                lua.DoString("str='chianr666'");                  //用C#脚本在lua环境中,创建一段lua脚本:str='chianr666'
                object[] values = lua.DoString("return num,str"); //用一个object数组 去接受返回值
                foreach (var value in values)                     //遍历 values 数组中的元素
                {
                    Console.WriteLine(value); //输出
                }
    
    
                lua.DoFile("Chinar.lua"); //加载lua文件 —— lua.DoFile(文件名)
    
    
                Program program = new Program(); //声明一个对象
                //lua.RegisterFunction 注册方法(注册到Lua中以后方法的名称,程序对象,程序的类型program.GetType().(传入C#中的方法名:需要是公有方法))
                lua.RegisterFunction("LuaChinarTest", program, program.GetType().GetMethod("ChinarTest"));
                //然后用lua.DoString(Lua中方法名())调用测试
                lua.DoString("LuaChinarTest()");
    
                //lua.RegisterFunction 注册静态方法(注册到Lua中以后方法的名称,空,程序的类型 typeof(Program).(传入C#中的方法名:需要是公有方法))
                lua.RegisterFunction("LuaChinarStaticTest", null, typeof(Program).GetMethod("ChinarStaticTest"));
                //然后用lua.DoString(Lua中静态方法名())调用测试
                lua.DoString("LuaChinarStaticTest()");
    
    
                lua.DoFile("ChinarClass.lua"); //Lua引用C#中的类
    
    
                Console.ReadKey(); //等待输入
            }
    
    
            /// <summary>
            /// 一个测试方法
            /// </summary>
            public void ChinarTest()
            {
                Console.WriteLine("这是一个空方法");
            }
    
    
            /// <summary>
            /// 一个静态测试方法
            /// </summary>
            public static void ChinarStaticTest()
            {
                Console.WriteLine("这个一个静态空方法");
            }
    
    
            public int    ChinarNum = 60;       //整形变量
            public string Name      = "Chinar"; //字符串变量
    
    
            /// <summary>
            /// 用来让Lua脚本测试的方法
            /// </summary>
            public void ChinarTestFun()
            {
                Console.WriteLine("你好,Chinar");
            }
    
    
            /// <summary>
            /// Ref方法,参数
            /// </summary>
            /// <param name="name"></param>
            /// <param name="count"></param>
            public void TestRef(string name, ref int count)
            {
                Console.WriteLine(name);
                Console.WriteLine(count);
                count = name.Length;
            }
    
    
            /// <summary>
            /// Out方法,参数
            /// </summary>
            /// <param name="name"></param>
            /// <param name="count"></param>
            public void TestOut(string name, out int count)
            {
                Console.WriteLine(name);
                count = name.Length;
            }
        }
    }

    Chinar.lua 文件

    print('I am Chianr')
    MyTable={1,22,333,4444,55555,666666}
    print(table.concat(MyTable)..'I am Chianr')

    ChinarClass.lua 文件

    -- 如果DeBug中有luanet.dll文件,则不需要再次引用
    -- require "luanet"
    -- 加载CLR类型("命名空间")
    luanet.load_assembly("System")
    -- 加载命名空间下的类
    Int32 = luanet.import_type("System.Int32")
    -- 输出
    print(Int32)
    print('- - - - - - - - - - - - - - - - - - - - - - - - - - ')
    
    
    -- 加载CLR类型("命名空间"ChinarTest)
    luanet.load_assembly("ChinarTest")
    -- 加载命名空间下的类Program
    Pro=luanet.import_type("ChinarTest.Program")
    
    -- 实例化一个类对象
    pro=Pro()
    -- 输出
    print(pro.ChinarNum)
    
    -- 调用C#中的方法
    pro:ChinarTestFun()
    
    -- 调用Out方法,out参数不需要传入值,会直接返回类型为一个:表
    -- 由于C#那边是一个空返回值的方法,所以第一个返回为空
    -- 第二个返回 out参数
    void,stringCount=pro:TestOut("chinar.fun")
    print(void,stringCount)
    
    -- Ref参数
    void1,stringCount1=pro:TestRef("chinar.fun",8)
    print(void1,stringCount1)

    输出结果:

    66
    chinar
    666
    chianr666
    I am Chianr
    122333444455555666666I am Chianr
    这是一个空方法
    这个一个静态空方法
    ProxyType(System.Int32): 12289376
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    60
    你好,Chinar
    chinar.fun
    nil     10
    chinar.fun
    8
    nil     10
    

    8

    Error —— 常见报错点


    报错点1:
    require “luanet” :如果DeBug中有luanet.dll文件,则不需要在Lua脚本中再次引用

    否则会报错:
    “LuaInterface.LuaException”类型的未经处理的异常在 LuaInterface.dll 中发生,其他信息: error loading module ‘luanet’ from file ‘.luanet.dll’


    报错点2:
    另外,修改 ChinarClass.lua 的属性后,一定要保存,不然还会报错找不到文件


    报错点3:
    注册的方法必须是 public ,否则会找不到


    报错点4:
    需要将写好的Lua文件拖到项目中,并且修改属性为 :如果较新则复制 / 始终复制

    否则会出现找不到文件的 报错信息


    报错点5:
    找到项目中的目录,并将下载好的 lua51.dll luanet.dll 两个文件,拷贝到DeBug文件目录中

    这一步,在第一步就做好,一步到位!





    Chinar

    Chinar的GitHub工程案例

    直接Down下来运行即可


    END

    本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

    对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com

    对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址

  • 相关阅读:
    Oracle学习笔记(oracle日期处理)
    Oralce学习笔记(plsql链接客户端)
    innerText和innerHTML应用
    oracle学习笔记(行转列列转行)
    js工作笔记基础一(分隔字符串)
    Oracle学习笔记(动态函数调用)
    理解!Page.IsPostBack和NET控件中的AutoPostBack
    oracle学习笔记(包头模板)
    div拖动层自己写
    oralce学习笔记(包体模板)
  • 原文地址:https://www.cnblogs.com/chinarbolg/p/9601452.html
Copyright © 2011-2022 走看看