如何在C#中集成Lua脚本
作者:Hello——寻梦者! 发布时间:2021-12-24 23:24:35
背景
在很多时候我们代码中的一些逻辑操作并不能够硬编码到代码中,我们可能希望通过配置来完成这个操作,所以这个时候我们就需要有一些脚本语言能够处理这些操作,在C#语言中比较常见的就是通过引入NLua这个动态库来引入lua脚本语言从而达到灵活配置的目的,这篇文章主要是通过具体的实例来说明在C#中如何通过引入NLua并调用配置的脚本。
步骤
1 引入NLua.dll
这个dll是一个很轻量级的库,100kb左右,引用这个库可以通过Nuget包管理器来引用,当前引用的版本是1.5.7.0,我们看看引用之后的添加了哪些DLL。
这个里面lua54.dll有x86和x64两个类型的版本,这个在使用的时候需要注意因为我们生成设置选择的是Any CPU所以这里会有两个版本的dll,这里使用的时候需要注意。
2 具体用法
下面通过一个控制台应用程序来看看这个脚本到底该怎么使用,这里包括直接创建表达式,注册方法并使用lua调用C#函数以及直接导入C#的库然后再调用里面内部的方法这三个方面进行描述。
2.1 直接创建表达式
我们来直接看控制台程序中的代码
class Program
{
static void Main(string[] args)
{
using (var state = new Lua())
{
//Evaluating simple expressions:
//Lua can return multiple values, for this reason DoString return a array of objects
var res0 = state.DoString("return 10 + 3*(5 + 2)")[0];
Console.WriteLine($"Output result0:{res0}");
//Passing raw values to the state:
double val = 12.0;
state["x"] = val; // Create a global value 'x'
var res1 = (double)state.DoString("return 10 + x*(5 + 2)")[0];
Console.WriteLine($"Output result1:{res1}");
//Retrieving global values:
state.DoString("y = 10 + x*(5 + 2)");
double y = (double)state["y"]; // Retrieve the value of y
Console.WriteLine($"Y result:{y}");
Console.ReadKey();
}
}}
注意事项:
首先来看这个注释:Lua can return multiple values, for this reason DoString return a array of objects,就是直接调用DoString方法的时候返回的结果是一个object[]类型,所以这里需要取结果的时候要取用第一个
2.2 注册Lua Function
这里我们通过直接在DoString中定义好function,然后通过Call方法进行调用,我们再来看下面的示例及返回结果
class Program
{
static void Main(string[] args)
{
using (var state = new Lua())
{
//Retrieving Lua functions:
state.DoString(@"function ScriptFunc (val1, val2)
if val1 > val2 then
return val1 + 1
else
return val2 - 1
end
end
");
var scriptFunc = state["ScriptFunc"] as LuaFunction;
var funcRes = scriptFunc.Call(3, 5).First();
Console.WriteLine($"Func result:{funcRes}");
Console.ReadKey();
}
}
}
同样的我们也来看看最终执行的结果
2.3 Lua调用C#函数
下面的例子包含了几种不同的参数类型及返回类型用来演示调用的完整过程。
using System;
using System.Linq;
using NLua;
namespace NLuaConsoleApp
{
class Program
{
static void Main(string[] args)
{
using (var state = new Lua())
{
////---------------------------------------------------lua调用c#函数
TestClass obj = new TestClass();
// 注册CLR对象方法到Lua,供Lua调用 typeof(TestClass).GetMethod("TestPrint")
state.RegisterFunction("TestPrint", obj, obj.GetType().GetMethod("TestPrint"));
// 注册CLR对象方法到Lua,供Lua调用 typeof(TestClass).GetMethod("AnotherFunc")
state.RegisterFunction("AnotherFunc", obj, obj.GetType().GetMethod("AnotherFunc"));
// 注册CLR静态方法到Lua,供Lua调用
state.RegisterFunction("TestStaticPrint", null, typeof(TestClass).GetMethod("TestStaticPrint"));
state.DoString("TestPrint(10,20)");
state.DoString("AnotherFunc('10','20')");
state.DoString("TestStaticPrint()");
Console.ReadKey();
}
}
class TestClass
{
public int TestPrint(int num,int num2)
{
var result = num + num2;
Console.WriteLine("Print result:" + result);
return result;
}
public void AnotherFunc(string val1, string val2)
{
Console.WriteLine($"MyTest,Param1:{val1},Param2:{val2}");
}
public static void TestStaticPrint()
{
Console.WriteLine("TestStaticPrint");
}
}
}
}
同样的我们来看整个测试的返回完整结果。
2.4 通过Import导入命名空间引用C#函数
这个是按照官方的例子进行模拟的,但是在调用的时候总是报错,现贴出具体的示例供后面排查使用
class Program
{
static void Main(string[] args)
{
using (var state = new Lua())
{
state.LoadCLRPackage();
state.DoString(@" import ('System.Web') ");
state.DoString(@" client = WebClient() ");
state.DoString(@"local res = client:DownloadString('http://nlua.org')");
Console.ReadKey();
}
}
}
这个就是说通过调用C#程序集并引入命名空间,然后调用其内部的WebClient方法,这个在调试的时候一直都是报错,这个暂时记录供以后进行排查错误
3 总结
这里有一些地方需要注意Lua对象是实现了IDispose接口的,所以我们在使用的时候需要注意使用using方式或者是使用后调用Dispose方法来对资源进行释放。另外C#中引入Lua脚本的常见主要是适用于部分调用过程不适合硬编码在代码里而适合放在配置中,通过配置不同的Lua脚本从而对程序进行定制化操作,是对现有代码一个很好的补充,另外对于调用C#中dll的方法出现的问题还在研究中,后面发现了再更新此过程。
来源:https://www.cnblogs.com/seekdream/p/14431273.html


猜你喜欢
- 在X86的环境下,var wParam = (int)msg.WParam;工作得很好。在X64的环境下,快速滚动滚轮会出现msg.WPar
- 一、代理模式 代理模式是常用的java设计模式,特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委
- 本文实例讲述了Android基于API的Tabs3实现仿优酷tabhost效果。分享给大家供大家参考,具体如下:前两天老师就让自己写个视频播
- OSS.Http项目对于.Net Standard标准库的支持已经迁移完毕,OSS开源系列两个最底层的类库已经具备跨运行时支持的能力。由于O
- 腾讯TBS浏览器服务我们都知道,在Android开发中,经常会用到Webview,而且WebView是出了名的坑的,各种bug。这时候腾讯老
- 前言坚持是一件比较难的事,坚持并不是自欺欺人的一种自我麻痹和安慰,也不是做给被人的,我觉得,坚持的本质并没有带着过多的功利主义,如果满是功利
- 目录一、String的用法1.构造方法2.求字符串长度和某一位置字符3.提取子串4.字符串比较5.字符串链接6.字符串中单个字符查找7.大小
- 1.Java 9以前堆栈遍历到目前为止,官方解决方案是获取当前线程并调用其getStackTrace()方法:StackTraceEleme
- 调用API设置鼠标位置并模拟鼠标右键让人物走动,全局钩子等using System;using System.Collections.Ge
- T4简介T4(Text Template Transformation Toolkit)在 Visual Studio 中,“T4 文本模板
- 有经验的程序员应该都见过,一个方法坐拥几十上百个参数。方法为何要有参数?因为不同方法间需共享信息。但方法间共享信息的方式不止一种,除了参数列
- Java调用shell命令涉及管道、重定向时不生效近日,因项目需求需要用java调用shell命令实现清理过时图片任务,发现代码生成出来的s
- 1.理解全过程1.1.概述需要具备的知识Socket网络编程反向代理的理解平滑加权轮询算法的理解线程池的理解目的:实现Socket 集群服务
- Android Studio是谷歌推出一个Android集成开发工具,基于IntelliJ IDEA。它类似于Eclipse ADT,And
- 引言在项目中,时间的使用必不可少,而java 8之前的时间api Date和Calander等在使用上存在着很多问题,于是,jdk1.8引进
- 前言最近碰到了Mybatis一对多查询的场景,在这里总结对比下常见的两种实现方式。本文以常见的订单表和订单详情表来举例说明;数据库表准备订单
- 什么是FlutterFlutter 是谷歌推出的开发移动UI框架,可以快速的在IOS和Android上构建高质量的原生用户界面。Flutte
- 一个应用场景,浏览器上传一个文件,此文件后台调用文件转换,需要耗费相当长的时间,这样,如果是一个线程同步式的做下去,那么用户在浏览器上感觉就
- 本文实例讲述了C#画笔使用复合数组绘制单个矩形的方法。分享给大家供大家参考。具体实现方法如下:using System;using Syst
- 对于Hibernate刚刚学习了一周时间了,作为一名java初学者,也有点自己的感受想分享出来,如果这篇文章能有幸被大家看到,也仅供大家娱乐