如何在C#中集成Lua腳本
背景
在很多時(shí)候我們代碼中的一些邏輯操作并不能夠硬編碼到代碼中,我們可能希望通過配置來完成這個(gè)操作,所以這個(gè)時(shí)候我們就需要有一些腳本語言能夠處理這些操作,在C#語言中比較常見的就是通過引入NLua這個(gè)動(dòng)態(tài)庫來引入lua腳本語言從而達(dá)到靈活配置的目的,這篇文章主要是通過具體的實(shí)例來說明在C#中如何通過引入NLua并調(diào)用配置的腳本。
步驟
1 引入NLua.dll
這個(gè)dll是一個(gè)很輕量級的庫,100kb左右,引用這個(gè)庫可以通過Nuget包管理器來引用,當(dāng)前引用的版本是1.5.7.0,我們看看引用之后的添加了哪些DLL。

這個(gè)里面lua54.dll有x86和x64兩個(gè)類型的版本,這個(gè)在使用的時(shí)候需要注意因?yàn)槲覀兩稍O(shè)置選擇的是Any CPU所以這里會(huì)有兩個(gè)版本的dll,這里使用的時(shí)候需要注意。
2 具體用法
下面通過一個(gè)控制臺(tái)應(yīng)用程序來看看這個(gè)腳本到底該怎么使用,這里包括直接創(chuàng)建表達(dá)式,注冊方法并使用lua調(diào)用C#函數(shù)以及直接導(dǎo)入C#的庫然后再調(diào)用里面內(nèi)部的方法這三個(gè)方面進(jìn)行描述。
2.1 直接創(chuàng)建表達(dá)式
我們來直接看控制臺(tái)程序中的代碼
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();
}
}}

注意事項(xiàng):
首先來看這個(gè)注釋:Lua can return multiple values, for this reason DoString return a array of objects,就是直接調(diào)用DoString方法的時(shí)候返回的結(jié)果是一個(gè)object[]類型,所以這里需要取結(jié)果的時(shí)候要取用第一個(gè)

2.2 注冊Lua Function
這里我們通過直接在DoString中定義好function,然后通過Call方法進(jìn)行調(diào)用,我們再來看下面的示例及返回結(jié)果
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();
}
}
}
同樣的我們也來看看最終執(zhí)行的結(jié)果

2.3 Lua調(diào)用C#函數(shù)
下面的例子包含了幾種不同的參數(shù)類型及返回類型用來演示調(diào)用的完整過程。
using System;
using System.Linq;
using NLua;
namespace NLuaConsoleApp
{
class Program
{
static void Main(string[] args)
{
using (var state = new Lua())
{
////---------------------------------------------------lua調(diào)用c#函數(shù)
TestClass obj = new TestClass();
// 注冊CLR對象方法到Lua,供Lua調(diào)用 typeof(TestClass).GetMethod("TestPrint")
state.RegisterFunction("TestPrint", obj, obj.GetType().GetMethod("TestPrint"));
// 注冊CLR對象方法到Lua,供Lua調(diào)用 typeof(TestClass).GetMethod("AnotherFunc")
state.RegisterFunction("AnotherFunc", obj, obj.GetType().GetMethod("AnotherFunc"));
// 注冊CLR靜態(tài)方法到Lua,供Lua調(diào)用
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");
}
}
}
}
同樣的我們來看整個(gè)測試的返回完整結(jié)果。

2.4 通過Import導(dǎo)入命名空間引用C#函數(shù)
這個(gè)是按照官方的例子進(jìn)行模擬的,但是在調(diào)用的時(shí)候總是報(bào)錯(cuò),現(xiàn)貼出具體的示例供后面排查使用
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();
}
}
}
這個(gè)就是說通過調(diào)用C#程序集并引入命名空間,然后調(diào)用其內(nèi)部的WebClient方法,這個(gè)在調(diào)試的時(shí)候一直都是報(bào)錯(cuò),這個(gè)暫時(shí)記錄供以后進(jìn)行排查錯(cuò)誤

3 總結(jié)
這里有一些地方需要注意Lua對象是實(shí)現(xiàn)了IDispose接口的,所以我們在使用的時(shí)候需要注意使用using方式或者是使用后調(diào)用Dispose方法來對資源進(jìn)行釋放。另外C#中引入Lua腳本的常見主要是適用于部分調(diào)用過程不適合硬編碼在代碼里而適合放在配置中,通過配置不同的Lua腳本從而對程序進(jìn)行定制化操作,是對現(xiàn)有代碼一個(gè)很好的補(bǔ)充,另外對于調(diào)用C#中dll的方法出現(xiàn)的問題還在研究中,后面發(fā)現(xiàn)了再更新此過程。
以上就是如何在C#中集成Lua腳本的詳細(xì)內(nèi)容,更多關(guān)于C#中集成Lua腳本的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
c#基數(shù)排序Radix sort的實(shí)現(xiàn)方法
這篇文章主要介紹了c#基數(shù)排序Radix sort的實(shí)現(xiàn)方法,有需要的朋友可以參考一下2014-01-01
當(dāng)用戶退出點(diǎn)擊瀏覽器后退仍可回到原來頁面的解決方案
這篇文章主要介紹了當(dāng)用戶退出點(diǎn)擊瀏覽器后退仍可回到原來頁面的解決方案 的相關(guān)資料,需要的朋友可以參考下2016-03-03
C# winForm實(shí)現(xiàn)的氣泡提示窗口功能示例
這篇文章主要介紹了C# winForm實(shí)現(xiàn)的氣泡提示窗口功能,涉及C# winForm窗口屬性與設(shè)置相關(guān)操作技巧,需要的朋友可以參考下2018-03-03
HttpWebRequest出錯(cuò).Section=ResponseHeader Detail=CR
HttpWebRequest出錯(cuò).Section=ResponseHeader Detail=CR...2007-03-03

