Lua基本语法-lua脚本与C#的交互(相当简单详细的例子)

简介: lua脚本 与 C#的交互本文提供全流程,中文翻译。Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例)...

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

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

相关文章
|
24天前
|
缓存 NoSQL 搜索推荐
【📕分布式锁通关指南 03】通过Lua脚本保证redis操作的原子性
本文介绍了如何通过Lua脚本在Redis中实现分布式锁的原子性操作,避免并发问题。首先讲解了Lua脚本的基本概念及其在Redis中的使用方法,包括通过`eval`指令执行Lua脚本和通过`script load`指令缓存脚本。接着详细展示了如何用Lua脚本实现加锁、解锁及可重入锁的功能,确保同一线程可以多次获取锁而不发生死锁。最后,通过代码示例演示了如何在实际业务中调用这些Lua脚本,确保锁操作的原子性和安全性。
56 6
【📕分布式锁通关指南 03】通过Lua脚本保证redis操作的原子性
|
16天前
|
JavaScript Shell C#
多种脚本批量下载 Docker 镜像:Shell、PowerShell、Node.js 和 C#
本项目提供多种脚本(Shell、PowerShell、Node.js 和 C#)用于批量下载 Docker 镜像。配置文件 `docker-images.txt` 列出需要下载的镜像及其标签。各脚本首先检查 Docker 是否安装,接着读取配置文件并逐行处理,跳过空行和注释行,提取镜像名称和标签,调用 `docker pull` 命令下载镜像,并输出下载结果。使用时需创建配置文件并运行相应脚本。C# 版本需安装 .NET 8 runtime。
94 1
|
1月前
|
NoSQL Redis 数据库
Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
通过本文的介绍,我们详细讲解了 Lua 脚本在 Redis 中的作用、`eval` 命令的使用方法以及 `redis.call` 和 `redis.pcall` 的区别和用法。通过合理使用 Lua 脚本,可以实现复杂的业务逻辑,确保操作的原子性,并减少网络开销,从而提高系统的性能和可靠性。
76 13
|
3月前
|
监控 安全
公司用什么软件监控电脑:Lua 脚本在监控软件扩展功能的应用
在企业环境中,电脑监控软件对保障信息安全、提升效率至关重要。Lua 脚本在此类软件中用于扩展功能,如收集系统信息、监控软件使用时长及文件操作,向指定服务器发送数据,支持企业管理和运营。
64 6
|
4月前
|
安全 Java C#
Unreal Engine C# 脚本编写浅谈
本文介绍了在 Unreal Engine 中使用 C# 编写脚本的方法,涵盖环境搭建、基础概念、常见问题及代码案例。从安装插件到处理输入事件和加载蓝图,详细讲解了如何在 Unreal Engine 中高效利用 C# 进行开发。
89 3
|
5月前
|
缓存 分布式计算 NoSQL
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
65 2
|
6月前
|
存储 JSON Ubuntu
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
|
7月前
|
图形学 C# 开发者
全面掌握Unity游戏开发核心技术:C#脚本编程从入门到精通——详解生命周期方法、事件处理与面向对象设计,助你打造高效稳定的互动娱乐体验
【8月更文挑战第31天】Unity 是一款强大的游戏开发平台,支持多种编程语言,其中 C# 最为常用。本文介绍 C# 在 Unity 中的应用,涵盖脚本生命周期、常用函数、事件处理及面向对象编程等核心概念。通过具体示例,展示如何编写有效的 C# 脚本,包括 Start、Update 和 LateUpdate 等生命周期方法,以及碰撞检测和类继承等高级技巧,帮助开发者掌握 Unity 脚本编程基础,提升游戏开发效率。
241 0
|
7月前
|
程序员 C#
C# 语法基础全解
C# 语言类型全解
52 0
|
7月前
|
存储 C# 索引
C# 集合语法全解
本文详细介绍了C#中的集合语法,涵盖Array、List、Queue、Stack、BitArray、Set、Dictionary以及自定义集合Collection的使用方法。主要内容包括: 1. **Array** 2. **List** 3. **Queue** 4. **Stack** 5. **BitArray** 6. **Set** 7. **Dictionary** 8. **自定义集合Collection** 此外,还简要介绍了字符串比较方法`string.Compare`的使用示例。
53 0