基于AScript的Lua脚本语言发布啦

AScript是一个开源的C#动态脚本解析执行引擎,支持扩展多种脚本语言,2026年8月12日正式发布了lua脚本语言AScript.Lang.Lua,快来试试吧!

一、介绍

支持 Lua 基础语法和数据类型,以及表、元表、面向对象、模块等功能。

二、安装

复制代码
1 install-package AScript
2 install-package AScript.Lang.Lua

三、使用说明

  • 命名空间:using AScript.Lang.Lua;
  • 常用数据类型:
    • nil: 空值
    • boolean: 布尔值 (true, false)
    • number: 数值 (整数和浮点数)
    • string: 字符串
    • table: 表 (数组)
  • 运算符
    • 算术运算符: +, -, *, /, %, ^ (幂), // (整数除法)
    • 关系运算符: <, >, <=, >=, ==, ~=
    • 逻辑运算符: and, or, not
    • 连接运算符: .. (字符串连接), # (长度)
    • 赋值运算符: =, +=, -=, *=, /=, %=, ^=, ..=
  • 控制结构
    • 条件语句: if ... then ... elseif ... then ... else ... end
    • while循环: while ... do ... end
    • repeat循环:repeat ... until ...
    • 数值for循环: for i = start, end, step do ... end
    • 泛型for循环: for v in expr do ... end
    • 泛型for循环: for i,v in expr do ... end
  • 函数定义: function name(args) ... end
  • 匿名函数:local f = function(args) ... end
  • 局部变量: local var = value
  • 表构造器
    • 数组风格: { value1, value2, value3 }
    • 字典风格: { key1 = value1, key2 = value2 }
    • 混合风格: { 1, 2, name = "test" }

1、注册语言

复制代码
1 Script.Langs.Set("lua", LuaLang.Instance);
2 // 可全局设置为默认语言
3 // Script.Langs.Set("lua", LuaLang.Instance, setDefault: true);

2、字符串连接

两个字符串连接使用..操作符而不是+操作符。

复制代码
1 var script = new Script();
2 script.Context.Langs = new[] { "lua" };
3 Assert.AreEqual("hello123", script.Eval("'hello'..123"));

3、数据打包/解包

复制代码
 1 // 打包
 2 string s = @"
 3 local format='<i4i4fc10'
 4 local hp=12500
 5 local mp=8700
 6 local atk=156.5
 7 local name='john'
 8 local data = string.pack(format, hp, mp, atk, name)
 9 print(#data) -- 控制台输出data长度
10 ";
11 var script = new Script();
12 script.Context.Langs = new[] { "lua" };
13 script.Eval(s);
14 // 解包
15 script.Eval("local a,b,c,d=string.unpack(format, data)");
16 Assert.AreEqual(12500, script.Eval("a"));
17 Assert.AreEqual(8700, script.Eval("b"));
18 Assert.AreEqual(156.5, script.Eval("c"));
19 Assert.AreEqual("john", script.Eval("d"));

4、条件语句

复制代码
 1 string code = @"
 2 local x = 10
 3 if x >= 10 and x < 50 then
 4     local a = 5
 5     local b = 15
 6     x = a + b + 80
 7 elseif x >= 50 and x < 100 then
 8     x = 200
 9 else
10     x = 300
11 end
12 x
13 ";
14 var script = new Script();
15 script.Context.Langs = new[] { "lua" };
16 Assert.AreEqual(100L, script.Eval(code));

5、while循环

复制代码
 1 string code = @"
 2 local i = 0
 3 local sum = 0
 4 while i < 5 do
 5     i = i + 1
 6     sum = sum + i
 7 end
 8 sum
 9 ";
10 var script = new Script();
11 script.Context.Langs = new[] { "lua" };
12 Assert.AreEqual(15L, script.Eval(code));

6、数值for循环

  • 语法:for i=start,end[,step] do ... end,其中step默认为1
  • 注:循环体内部改变循环变量i的值,不影响循环次数
复制代码
 1 string code = @"
 2 local sum = 0
 3 for i = 1, 5 do
 4     i = i + 10
 5     sum = sum + i
 6 end
 7 sum
 8 ";
 9 var script = new Script();
10 script.Context.Langs = new[] { "lua" };
11 Assert.AreEqual(65L, script.Eval(code));

7、泛型for循环

复制代码
 1 string code = @"
 2 local sum = 0
 3 -- for v in ipairs({1, 2, 3, 4, 5}) do
 4 for i, v in ipairs({1, 2, 3, 4, 5}) do
 5     sum = sum + v
 6 end
 7 sum
 8 ";
 9 var script = new Script();
10 script.Context.Langs = new[] { "lua" };
11 Assert.AreEqual(15L, script.Eval(code));

8、函数

复制代码
 1 string code = @"
 2 function factorial(n)
 3     if n <= 1 then
 4         return 1
 5     end
 6     return n * factorial(n - 1)
 7 end
 8 factorial(5)
 9 ";
10 var script = new Script();
11 script.Context.Langs = new[] { "lua" };
12 Assert.AreEqual(120L, script.Eval(code));

9、表(数组)

复制代码
1 string code = @"
2 local arr = {10, 20, 30}
3 arr[1] + arr[2] + arr[3]
4 ";
5 var script = new Script();
6 script.Context.Langs = new[] { "lua" };
7 Assert.AreEqual(60L, script.Eval(code));

10、表(字典)

复制代码
 1 string code = @"
 2 local t = { x = 3, y = 5 }
 3 t.sum = function(a,b) 
 4     print(a,b)
 5     return a+b 
 6 end
 7 t.sum(t.x,t.y)
 8 ";
 9 var script = new Script();
10 script.Context.Langs = new[] { "lua" };
11 Assert.AreEqual(8L, script.Eval(code));

11、元表

复制代码
1 string code = @"
2 local t = {}
3 local metatable = { __index = { name = 'tom' } }
4 setmetatable(t, metatable)
5 t.name
6 ";
7 var script = new Script();
8 script.Context.Langs = new[] { "lua" };
9 Assert.AreEqual("tom", script.Eval(code));

12、面向对象(OOP)

复制代码
 1 string code = @"
 2 -- 定义动物类(Animal)
 3 Animal = {name = 'Unknown'}
 4 
 5 -- Animal 类的构造函数
 6 function Animal:new(name)
 7   local o = {}
 8   setmetatable(o, self)  -- 设置元表,使其继承 Animal 的方法
 9   self.__index = self  -- 让对象可以访问 Animal 的方法
10   o.name = name or 'Unknown'  -- 设置名称,默认为 'Unknown'
11   return o
12 end
13 
14 -- Animal 类的方法:叫声
15 function Animal:speak()
16   return self.name .. ' makes a sound.'
17 end
18 
19 -- 定义狗类(Dog),继承自 Animal
20 Dog = Animal:new()  -- Dog 继承 Animal 类
21 
22 -- 重写狗类的构造函数
23 function Dog:new(name, breed)
24   local o = {}
25   setmetatable(o, self)  -- 设置元表,使其继承 Dog 和 Animal 的方法
26   self.__index = self  -- 让对象可以访问 Dog 的方法
27   o.name = name or 'Unknown'
28   o.breed = breed or 'Unknown'
29   return o
30 end
31 
32 -- 重写狗类的叫声方法(重写 Animal 的 speak 方法)
33 function Dog:speak()
34   return self.name .. ' barks.'
35 end
36 
37 -- 创建 Animal 对象
38 local animal = Animal:new('Generic Animal')
39 local s1 = animal:speak()  -- 输出 'Generic Animal makes a sound.'
40 
41 -- 创建 Dog 对象
42 local dog = Dog:new('Buddy', 'Golden Retriever')
43 local s2 = dog:speak()  -- 输出 'Buddy barks.'
44 s1 .. ';' .. s2
45 ";
46 var script = new Script();
47 script.Context.Langs = new[] { "lua" };
48 Assert.AreEqual("Generic Animal makes a sound.;Buddy barks.", script.Eval(code));

13、模块

使用require引入模块,优先查找IScriptModule模块,再查找模块目录中的模块文件。

1)添加模块目录

复制代码
1 LuaLang.Instance.Modules.AddDir("./lua/modules");

2)模块目录中添加Person.lua文件

复制代码
 1 Person = {name = '', age = 0}
 2 
 3 function Person:new(name, age)
 4     local obj = {}  -- 创建一个新的表作为对象
 5     setmetatable(obj, self)  -- 设置元表,使其成为 Person 的实例
 6     self.__index = self  -- 设置索引元方法,指向 Person
 7     obj.name = name
 8     obj.age = age
 9     return obj
10 end
11 
12 function Person:introduce()
13     return 'My name is ' .. self.name .. ' and I am ' .. self.age .. ' years old.'
14 end
15 
16 return Person

3)引入并使用模块

复制代码
1 string code = @"
2 require 'Person'
3 local person1 = Person:new('Alice', 30)
4 person1:introduce()
5 ";
6 var script = new Script();
7 script.Context.Langs = new[] { "lua" };
8 Assert.AreEqual("My name is Alice and I am 30 years old.", script.Eval(code));

14、io模块

文件操作,服务端请谨慎使用,避免脚本恶意修改、删除文件。

1)安装模块

复制代码
1 install-package AScript.Lang.Lua.io

2)注册io模块

复制代码
1 LuaLang.Instance.Modules.Add("io", new AScript.Lang.Lua.io.LuaIOModule());

3)使用io

复制代码
 1 string code = @"
 2 require 'io'
 3 local f = io.open(file, 'w')
 4 f:write('hello')
 5 f:close()
 6 local f = io.open(file, 'r')
 7 local content = f:read()
 8 f:close()
 9 content
10 ";
11 var script = new Script();
12 script.Context.Langs = new[] { "lua" };
13 script.Context.SetVar("file", "./test.txt");
14 Assert.AreEqual("hello", script.Eval(code));

四、与宿主程序交互

1、脚本调用C#函数

复制代码
 1 var code = @"
 2 local a = 10
 3 local b = 20
 4 sum(a, b)
 5 ";
 6 var script = new Script();
 7 script.Context.Langs = new[] { "lua" };
 8 // 注入函数
 9 script.Context.AddFunc<long, long, long>("sum", (x, y) => x + y);
10 Assert.AreEqual(30L, script.Eval(code));

2、C#调用脚本中的函数

复制代码
 1 var code = @"
 2 function sum(x,y)
 3     return x+y
 4 end
 5 local a = 10
 6 local b = 20
 7 sum(a, b)
 8 ";
 9 var script = new Script();
10 script.Context.Langs = new[] { "lua" };
11 Assert.AreEqual(30L, script.Eval(code));
12 // 获取脚本中的函数
13 var sum = script.Context.GetFunc<long, long, long>("sum");
14 Assert.AreEqual(80L, sum(30, 50));

五、结束语

更多语法、功能请参考Lua 教程 | 菜鸟教程

AScript开源地址:https://gitee.com/rockey627/AScript

相关推荐
半亩码田4 小时前
【.NET新特性·第11篇】C# 14 字段属性:告别手写 backing field
java·c#·.net
曹牧4 小时前
C#:问号
前端·数据库·c#
少控科技5 小时前
农场设备管理代码(2)
开发语言·c#
唐青枫7 小时前
别再把命令行参数写成一团:C#.NET System.CommandLine 实战详解
c#·.net
hez20107 小时前
让 .NET 11 的泛型虚方法变得更快!
c#·.net·.net core·clr·compiler
宝桥南山8 小时前
Microsoft Agent Framework(.NET) - 尝试一下从MCP Server上获取Agent Skills
ai·微软·c#·aigc·.net·.netcore
少控科技10 小时前
农场设备管理代码(1)
开发语言·c#
海盗123413 小时前
微软技术日报·2026-08-12——Windows 11多通道累积更新推送十余项功能改进;.NET WebSocket DoS紧急修复
windows·microsoft·.net
椒颜皮皮虾྅1 天前
OpenVINO C# API 3.3.1:支持OpenVINO 2026.3及GenAI增强
人工智能·c#·openvino