MoonSharp 文檔一

目錄

1.Getting Started

步驟1:在 IDE 中引入 MoonSharp

步驟2:引入命名空間

步驟3:調用腳本

步驟4:運行代碼

2.Keeping a Script around

步驟1:復現前教程所有操作

步驟2:改為創建Script對象

步驟3:訪問全局環境

步驟4:直接調用函數

3.DynValue revealed

步驟1:重新執行你在上一個教程中的所有操作

步驟2:將 fact 函數存入 DynValue

步驟3:將數字存入 DynValue

步驟 4:了解 DataType(s)

步驟 5:元組

4.Calling back C#

步驟 1:永遠不要厭倦階乘

步驟 2:自定義乘法函數

返回一系列數字

返回表格

接收一個表

5.Auto-conversions

自定義轉換器

CLR 類型到 MoonSharp 類型的自動轉換

MoonSharp 類型到 CLR 類型的標準自動轉換

MoonSharp 類型到 CLR 類型的受限自動轉換


文檔地址:

MoonSharp

1.Getting Started

您的第一個 MoonSharp 項目的快速指南

本教程將帶你初步體驗 MoonSharp 的簡潔與強大。雖然 MoonSharp 有更優的使用方式,但這是最基礎的一種。其他教程會深入探討如何充分發揮 MoonSharp 的潛力。現在,讓我們開始吧!


關于語言支持的說明
本網站大多數教程僅提供 C# 示例,但本頁會為 VB.NET 用戶提供一些指引。
MoonSharp 兼容所有 CLR 語言(C#、VB.NET、C++/CLI、F#、Boo 等),理論上也支持DLR語言(如 IronPython、IronRuby)。但由于維護多語言示例的工作量較大,后續教程僅提供 C# 示例(本入門頁含 VB.NET)。
大多數教程的代碼可在 GitHub 的示例項目中找到。
學習前提:需熟悉Lua和至少一門.NET語言(推薦 C#),否則可能難以理解示例。


步驟1:在 IDE 中引入 MoonSharp

根據使用的IDE(Visual Studio、MonoDevelop、SharpDevelop、Unity)選擇以下方式:

Visual Studio(通過 NuGet)
1.在包管理器控制臺輸入:

PM> Install-Package MoonSharp ?

2.或右鍵“引用”->“管理NuGet包”->搜索“MoonSharp”并安裝。

Xamarin Studio(通過NuGet)
菜單欄選擇“項目”->“添加NuGet包”->搜索“MoonSharp”并安裝。

其他IDE(手動添加)
將 MoonSharp 發行包中對應平臺的 MoonSharp.Interpreter.dll 添加為項目依賴。

Unity
1.推薦方式:通過Asset Store安裝(待審核后在此鏈接提供)。

2.手動方式:
將 interpreter/net35 目錄下的 MoonSharp.Interpreter.dll 放入 Assets/Plugins。
若需支持 Windows Store/WP:
?? ?將 interpreter/portable-net40 下的 DLL放入 Assets/Plugins/WSA。
?? ?參考此指南配置。鏈接

3.IL2CPP項目:
在 Assets 目錄下創建/編輯 link.xml,內容如下:

<linker> ?<assembly fullname="MoonSharp.Interpreter"> ?<type fullname="MoonSharp.*" preserve="all" /> ?</assembly> ?
</linker> ?

步驟2:引入命名空間

在代碼頂部添加:
C#

using MoonSharp.Interpreter; ?

VB.NET

Imports MoonSharp.Interpreter ?

步驟3:調用腳本

以下示例演示如何用MoonSharp計算階乘:

C#

double MoonSharpFactorial()
{string script = @"    -- defines a factorial functionfunction fact (n)if (n == 0) thenreturn 1elsereturn n*fact(n - 1)endendreturn fact(5)";DynValue res = Script.RunString(script);return res.Number;
}

VB.NET

Function MoonSharpFactorial() As Double' VB.NET is not very strong at embedded newlines...Dim scriptCode As String = "-- defines a factorial function" & vbCrLf &"function fact (n)" & vbCrLf & _"if (n == 0) then" & vbCrLf & _"return 1" & vbCrLf & _"else" & vbCrLf & _"return n*fact(n - 1)" & vbCrLf & _"end" & vbCrLf & _"end" & vbCrLf & _"return fact(5)" & vbCrLfDim res As DynValue = Script.RunString(scriptCode)Return res.Number
End Function

步驟4:運行代碼

在代碼中調用MoonSharpFactorial()即可執行腳本。現在,你可以繼續探索其他教程了!
?

2.Keeping a Script around

言語易逝,文字永存。

在之前的教程中,你首次接觸了 MoonSharp:將腳本放入字符串中運行并獲取輸出。雖然偶爾有用,但大多數實際用例需要的互操作性需要 CLR 代碼與 MoonSharp 更深度的集成。

步驟1:復現前教程所有操作

認真地說,雖然我們在這里學習的是(稍微)更高級的概念,但你最初的嘗試幾乎無需改動。這正是一個極好的起點。

步驟2:改為創建Script對象

首先要做的更改是創建一個腳本對象,而不是使用靜態方法之一。這并非什么難事,但它為我們接下來的發展奠定了基礎。

double MoonSharpFactorial()
{string scriptCode = @"    -- defines a factorial functionfunction fact (n)if (n == 0) thenreturn 1elsereturn n*fact(n - 1)endendreturn fact(5)";Script script = new Script();DynValue res = script.DoString(scriptCode);return res.Number;
}

步驟3:訪問全局環境

現在有了腳本對象,我們可以修改函數運行的全局環境。例如,改變階乘函數的輸入參數,讓程序能指定計算目標數值的階乘。
?

double MoonSharpFactorial()
{string scriptCode = @"    -- defines a factorial functionfunction fact (n)if (n == 0) thenreturn 1elsereturn n*fact(n - 1)endendreturn fact(mynumber)";Script script = new Script();script.Globals["mynumber"] = 7;DynValue res = script.DoString(scriptCode);return res.Number;
}

通過簡單的 script.Globals 表引用語法,我們實現了向 MoonSharp 腳本注入數值。實際上不僅能傳遞數字,后續還將演示如何傳遞函數和對象,但現階段我們暫限于數字、布爾值和字符串。

步驟4:直接調用函數

我們學習了如何讓 MoonSharp 計算從外部選擇的數字的階乘。但是,以這種方式完成,感覺像是一個骯臟的黑客行為(盡管如此,這是一項重要的技術,我們將經常使用)。

下面是如何從C#調用Lua函數。

double MoonSharpFactorial2()
{string scriptCode = @"    -- defines a factorial functionfunction fact (n)if (n == 0) thenreturn 1elsereturn n*fact(n - 1)endend";Script script = new Script();script.DoString(scriptCode);DynValue res = script.Call(script.Globals["fact"], 4);return res.Number;
}

我們來看看具體做了哪些調整。

首先,我們刪除了腳本結尾的 return 語句——這個語句本來可以保留,但由于我們需要通過自定義參數調用 fact 函數,保留它反而會導致冗余。

此時,script.DoString(...)? 的調用將會執行整個腳本文件,在全局環境中留下一個完整可用的 fact 函數。

隨后我們添加了這一行代碼:

DynValue res = script.Call(script.Globals["fact"], 4);

這段代碼會從腳本的全局環境中獲取 fact 函數,并以參數4進行調用。

雖然存在更高效的實現方式(特別是在性能方面),但如果您不需要在時間敏感的循環中進行大量調用,這無疑是最簡單的解決方案(不過存在一定的類型安全隱患)。

值得注意的是,fact 函數可以任意次數被調用——因為 Script 會保留其運行狀態,并隨時準備好被反復執行。

3.DynValue revealed

一切皆是 DynValue,DynValue 即一切。

DynValue 概念實際上是 MoonSharp 的核心基礎,盡管到目前為止我們幾乎沒有涉及太多,但事實上,想要深入了解而不觸及這一主題是不太可能的。

如標題所述,MoonSharp 中的(幾乎)所有內容都是 DynValue 對象的實例。一個 DynValue 代表腳本中的一個值,無論其類型如何,因此它可以是一個表、一個函數、一個數字、一個字符串或其他任何東西。

那么,讓我們從最新的教程步驟開始,并將其改為使用 DynValue。

步驟1:重新執行你在上一個教程中的所有操作

我們再次從上一個教程的最后一步開始。你已經完成了吧?

你可以在這里獲取參考文檔。

步驟2:將 fact 函數存入 DynValue

第一個改動是我們以不同的方式獲取 fact 變量:

double MoonSharpFactorial()
{string scriptCode = @"    -- defines a factorial functionfunction fact (n)if (n == 0) thenreturn 1elsereturn n*fact(n - 1)endend";Script script = new Script();script.DoString(scriptCode);DynValue luaFactFunction = script.Globals.Get("fact");DynValue res = script.Call(luaFactFunction, 4);return res.Number;
}

好的,讓我們在這一行花點時間:

DynValue luaFactFunction = script.Globals.Get("fact");

這樣可以從腳本的全局作用域中獲取 fact 函數。與索引器屬性不同,「Get」方法會直接返回一個「DynValue」類型,而索引器則會嘗試將其轉換為「System.Object」。在本例中,由于我們需要獲取的是「DynValue」類型,因此選擇使用「Get」方法。

步驟3:將數字存入 DynValue

如果我們希望避免額外的類型轉換,可以直接以「DynValue」形式傳遞數字,而無需依賴「Call」方法提供的隱式轉換。雖然當前場景中這不是必需的,但在其他情況下可能會用到,畢竟并非所有操作都會自動幫你完成類型轉換!

double MoonSharpFactorial2()
{string scriptCode = @"    -- defines a factorial functionfunction fact (n)if (n == 0) thenreturn 1elsereturn n*fact(n - 1)endend";Script script = new Script();script.DoString(scriptCode);DynValue luaFactFunction = script.Globals.Get("fact");DynValue res = script.Call(luaFactFunction, DynValue.NewNumber(4));return res.Number;
}

所以,我們用以下內容替換了我們的數字:

DynValue.NewNumber(4)

DynValue 有許多工廠方法,都以 "New" 開頭(如 NewString、NewNumber、NewBoolean 等),可用于從頭開始構建我們的值。

它還有一個方便的 FromObject 方法,可以從對象創建 DynValue,這正是 Call 在幕后使用的方法,以簡化我們的工作。

步驟 4:了解 DataType(s)

在 DynValue 中,最重要的屬性之一是 Type。

Type 屬性是一個枚舉,告訴我們 DynValue 中包含了什么類型的數據。

每當我們想知道 DynValue 中包含了什么,我們都可以查詢 Type 屬性:

// Create a new number
DynValue v1 = DynValue.NewNumber(1);
// and a new string
DynValue v2 = DynValue.NewString("ciao");
// and another string using the automagic converters
DynValue v3 = DynValue.FromObject(new Script(), "hello");// This prints Number - String - String
Console.WriteLine("{0} - {1} - {2}", v1.Type, v2.Type, v3.Type);
// This prints Number - String - Some garbage number you shouldn't rely on to be 0
Console.WriteLine("{0} - {1} - {2}", v1.Number, v2.String, v3.Number);

重要的是要知道,DynValue 的某些屬性只有在值是給定類型時才有意義。例如,只有當類型為 DataType.Number 時,Number 屬性才能保證有意義的值,String 屬性也是如此。

除非你確定 DynValue 包含什么,否則在使用其屬性之前,請務必檢查 DynValue 的 Type。假設 DynValue 包含一個給定類型,而它實際上包含另一個類型,這是錯誤和問題的常見來源。

步驟 5:元組

正如你(應該)知道的,Lua 可以從函數(以及其他情況)返回多個值。

為了處理這種情況,使用了一種特殊的 DynValue 類型(DataType.Tuple)。元組有一個 Tuple 屬性,它是 DynValue 對象的數組,這些對象是元組的成員。

這比聽起來更簡單:

DynValue ret = Script.RunString("return true, 'ciao', 2*3");// prints "Tuple"
Console.WriteLine("{0}", ret.Type);// Prints:
//   Boolean = true
//   String = "ciao"
//   Number = 6
for (int i = 0; i < ret.Tuple.Length; i++)Console.WriteLine("{0} = {1}", ret.Tuple[i].Type, ret.Tuple[i]);

結語

關于 DynValue 的介紹就到這里。還有很多需要學習的內容,但這些應該足以讓你入門了。

請記住這些內容,因為這是一切的核心。

4.Calling back C#

但也支持 F# 和 VB.NET 和 C++/CLI 和 Boo 等等...

腳本在應用程序中非常有用,因為它們可以從包含應用程序本身實現的構建塊開始,自定義業務邏輯。無論您是在商業應用程序、視頻游戲還是某種工具中嵌入腳本,您的首要關注點是腳本和應用程序的互操作性以及兩者之間的對象共享(在某種意義上)。

而過程編程中的基本構建塊是函數。

步驟 1:永遠不要厭倦階乘

讓我們從到目前為止我們使用的標準階乘腳本開始:

private static double CallbackTest()
{string scriptCode = @"    -- defines a factorial functionfunction fact (n)if (n == 0) thenreturn 1elsereturn n * fact(n - 1);endend";Script script = new Script();script.DoString(scriptCode);DynValue res = script.Call(script.Globals["fact"], 4);return res.Number;
}

步驟 2:自定義乘法函數

好的,假設我們希望乘法在宿主應用程序的 API 函數中實現。在這種情況下,這樣做顯然沒有任何目的,但我們在這里是為了學習,所以讓我們假裝這是一個好主意。

private static int Mul(int a, int b)
{return a * b;
}private static double CallbackTest()
{string scriptCode = @"    -- defines a factorial functionfunction fact (n)if (n == 0) thenreturn 1elsereturn Mul(n, fact(n - 1));endend";Script script = new Script();script.Globals["Mul"] = (Func<int, int, int>)Mul;script.DoString(scriptCode);DynValue res = script.Call(script.Globals["fact"], 4);return res.Number;
}

就是這樣!

script.Globals["Mul"] = (Func<int, int, int>)Mul;

這將全局環境中的 Mul 變量設置為指向應用程序的 Mul 委托。我們在這里將委托強制轉換為它的 Func<int, int, int> 類型以取悅 C# 編譯器 - 無論您使用什么技術將委托強制轉換為 System.Object 都可以。

另外,請注意,我們將方法定義為靜態的,但在這種情況下,它們完全不需要是靜態的;實例方法也可以使用。

返回一系列數字

問題:有一個API函數,它返回一個整數序列。腳本將對收到的數字求和,并返回總數。

private static IEnumerable<int> GetNumbers()
{for (int i = 1; i <= 10; i++)yield return i;
}private static double EnumerableTest()
{string scriptCode = @"    total = 0;for i in getNumbers() dototal = total + i;endreturn total;";Script script = new Script();script.Globals["getNumbers"] = (Func<IEnumerable<int>>)GetNumbers;DynValue res = script.DoString(scriptCode);return res.Number;
}

在這里,也沒有太難的地方。你可以看到如何將一個 IEnumerable(或 IEnumerator)即時轉換為 Lua 迭代器,以便腳本運行。

還要注意,腳本中直接包含了可執行代碼,因此在 DoString 時刻就可以訪問 getNumbers 方法,無需進行 Call.. 調用。記住這一點,DoString 和 DoFile 將立即執行腳本中包含的代碼!

還有一點必須注意。MoonSharp 能夠轉換 System.Collections.IEnumerable 和 System.Collections.IEnumerator 類型的迭代器。也就是說,非泛型的變體。如果由于某種原因你實現了一個泛型迭代器而沒有實現非泛型迭代器,那么迭代器將無法工作。所有標準的集合類型和迭代器方法,如上面的方法,默認實現了非泛型變體,所以不需要太擔心。

返回表格

問題:有一個API函數,這次返回一個整數序列,存儲在一個表格中。

private static List<int> GetNumberList()
{List<int> lst = new List<int>();for (int i = 1; i <= 10; i++)lst.Add(i);return lst;
}private static double TableTest1()
{string scriptCode = @"    total = 0;tbl = getNumbers()for _, i in ipairs(tbl) dototal = total + i;endreturn total;";Script script = new Script();script.Globals["getNumbers"] = (Func<List<int>>)GetNumberList;DynValue res = script.DoString(scriptCode);return res.Number;
}

在這里,我們可以看到 List<int> 是如何自動轉換為 Lua 表的!請注意,生成的表將像 Lua 表通常那樣以1為索引。

然而,我們可以做得更好。我們可以直接在函數內部構建一個 Lua 表:

private static Table GetNumberTable(Script script)
{Table tbl = new Table(script);for (int i = 1; i <= 10; i++)tbl[i] = i;return tbl;
}private static double TableTest2()
{string scriptCode = @"    total = 0;tbl = getNumbers()for _, i in ipairs(tbl) dototal = total + i;endreturn total;";Script script = new Script();script.Globals["getNumbers"] = (Func<Script, Table>)(GetNumberTable);DynValue res = script.DoString(scriptCode);return res.Number;
}

您可以看到使用 Table 對象操作表是多么容易。

但是有兩點需要注意:

要創建一個新的 Table 對象,您必須有一個對正在執行的腳本的引用
如果在 CLR 函數中有一個 Script 參數可供 Lua 腳本使用,MoonSharp 將為您填充它。這也適用于(不太可能以這種方式使用的)ScriptExecutionContext 和 CallbackArguments 類型。如果您不知道這些是做什么的,不用擔心,它們不是讓 MoonSharp 基本工作所必需的!
作為一個好的實踐,如果可以的話,總是保留 Script 對象。有些事情(比如創建表)只能使用 Script 對象來完成。

接收一個表

一個表會自動轉換為 List<T>。例如:

public static double TableTestReverse()
{string scriptCode = @"    return dosum { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }";Script script = new Script();script.Globals["dosum"] = (Func<List<int>, int>)(l => l.Sum());DynValue res = script.DoString(scriptCode);return res.Number;
}

但是,這可能會在某些平臺(比如 iOS)上造成問題。有很多方法可以解決這個問題(你會在其他教程中看到),但可以說,以下方法沒有任何問題,而且速度更快:

public static double TableTestReverseSafer()
{string scriptCode = @"    return dosum { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }";Script script = new Script();script.Globals["dosum"] = (Func<List<object>, int>)(l => l.OfType<int>().Sum());DynValue res = script.DoString(scriptCode);return res.Number;
}

另一種更快的方法是使用 Table 對象:

static double Sum(Table t)
{var nums = from v in t.Valueswhere v.Type == DataType.Numberselect v.Number;return nums.Sum();
}private static double TableTestReverseWithTable()
{string scriptCode = @"    return dosum { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }";Script script = new Script();script.Globals["dosum"] = (Func<Table, double>)Sum;DynValue res = script.DoString(scriptCode);return res.Number;
}

但在這里,我們必須處理 DynValue(s)。

要理解所有這些,我們需要更深入地了解 MoonSharp 如何將 Lua 類型映射到 C# 類型,反之亦然。我們將在下一部分中詳細討論。

5.Auto-conversions

這次沒有代碼。

在深入探討 MoonSharp 和 CLR 集成之前,我們需要明確類型是如何來回映射的。遺憾的是,反向映射與正向映射有很大不同,因此我們將分別分析這兩種情況。

你可能會問,這是不是有點太復雜了?

當然復雜。自動化的東西很好,但當它們失敗時,失敗的方式卻非常復雜。當有疑問或事情變得過于復雜時,你需要簡化事情。

有兩種方法:要么直接使用 DynValue,要么使用自定義轉換器。

這兩種解決方案不僅能讓你獲得理智和簡單,而且在速度上也明顯快于自動轉換!

自定義轉換器

可以自定義轉換過程,但設置是全局的,會影響所有腳本。

要自定義轉換,只需將適當的回調設置為 Script.GlobalOptions.CustomConverters。

例如,如果我們希望在從 CLR 轉換為腳本時,將所有 StringBuilder 對象轉換為大寫字符串,可以這樣做:

Script.GlobalOptions.CustomConverters.SetClrToScriptCustomConversion<StringBuilder>(v => DynValue.NewString(v.ToString().ToUpper()));

如果我們想自定義所有表格在與 IList<int> 匹配時的轉換方式,我們可以這樣寫:

Script.GlobalOptions.CustomConverters.SetScriptToClrCustomConversion(DataType.Table, typeof(IList<int>),v => new List<int>() { ... });

如果一個轉換器返回 null,系統會表現得就像沒有自定義轉換器存在一樣,并嘗試進行自動轉換。

CLR 類型到 MoonSharp 類型的自動轉換

這個轉換適用于以下情況:

? 從腳本調用的函數返回對象時
? 從用戶數據的屬性返回對象時 ?
? 使用索引運算符在表中設置值時
? 調用 DynValue.FromObject 時
? 使用任何以 System.Object 代替 DynValue 作為參數的函數重載時

這個轉換實際上非常簡單。下表解釋了具體的轉換規則:

CLR typeC# friendly nameLua typeNotes
void(no value)

This can be applied to return values of methods only.

翻譯:這只能應用于方法的返回值。

nullnil

Any null will be converted to nil.

翻譯:任何null都將轉換為nil。

MoonSharp.Interpreter.DynValue*

The DynValue is passed through.

翻譯:DynValue 被傳遞了。

System.SBytesbytenumber
System.Bytebytenumber
System.Int16shortnumber
System.UInt16ushortnumber
System.Int32intnumber
System.UInt32uintnumber
System.Int64longnumber

The conversion can lead to a silent precision loss.

翻譯:轉換可能導致精度無聲地丟失。

System.UInt64ulongnumber

The conversion can lead to a silent precision loss.

翻譯:轉換可能導致精度無聲地丟失。

System.Singlefloatnumber
System.Decimaldecimalnumber

The conversion can lead to a silent precision loss.

翻譯:轉換可能導致精度無聲地丟失。

System.Doubledoublenumber
System.Booleanboolboolean
System.Stringstringstring
System.Text.StringBuilderstring
System.Charcharstring
MoonSharp.Interpreter.Tabletable
MoonSharp.Interpreter.CallbackFunctionfunction
System.Delegatefunction
System.Objectobjectuserdata

Only if the type has been registered for userdata.

翻譯:只有當該類型已經為 userdata 注冊過,才可以這樣做。

System.Typeuserdata

Only if the type has been registered for userdata, static members access.

翻譯:只有當類型已經為 userdata 注冊時,才可以訪問靜態成員。

MoonSharp.Interpreter.Closurefunction
System.Reflection.MethodInfofunction
System.Collections.IListtable

The resulting table will be indexed 1-based. All values are converted using these rules.

翻譯:生成的表將使用從1開始的索引。所有的值都會按照以下規則進行轉換。

System.Collections.IDictionarytable

All keys and values are converted using these rules.

翻譯:所有鍵和值都會使用這些規則進行轉換。

System.Collections.IEnumerableiterator

All values are converted using these rules.

翻譯:所有值均依下列規則進行轉換。

System.Collections.IEnumeratoriterator

All values are converted using these rules.

翻譯:所有值均依下列規則進行轉換。

這包括對集合的相當全面的覆蓋,因為大多數集合都實現了 IList、IDictionary、IEnumerable 和/或 IEnumerator 接口。如果你正在編寫自己的集合,請記得實現這些非泛型接口中的一個。

任何不能使用此邏輯轉換的值都將拋出 ScriptRuntimeException。

MoonSharp 類型到 CLR 類型的標準自動轉換

相反的轉換要復雜得多。實際上,存在兩條不同的轉換路徑--"標準"路徑和"受限"路徑。當你要求將一個 DynValue 轉換為對象而不指定你實際想要接收什么時,應用第一種路徑,而當有一個目標 System.Type 要匹配時,則應用另一種路徑。

這在以下情況下使用:

  • 調用 DynValue.ToObject 時
  • 使用索引器從表中檢索值時
  • 在受限轉換的一些特定子情況下(見下文)

這里我們看到默認轉換。它實際上很簡單:

MoonSharp typeCLR typeNotes
nilnull

Applied to every value which is nil.

翻譯:應用于每個值為 nil 的情況。

booleanSystem.Boolean
numberSystem.Double
stringSystem.String
functionMoonSharp.Interpreter.Closure

If DataType is Function.

翻譯:如果數據類型是函數(Function)。

functionMoonSharp.Interpreter.CallbackFunction

If DataType is ClrFunction.

翻譯:如果數據類型是 CLR 函數(ClrFunction)。

tableMoonSharp.Interpreter.Table
tupleMoonSharp.Interpreter.DynValue[]
userdata(special)

Returns the object stored in userdata. If a "static" userdata, the Type is returned.

翻譯:如果是存儲在 userdata 中的對象,此方法會返回該對象。如果是“靜態”userdata,則返回其類型(Type)。

無法使用此邏輯轉換的每個值都將拋出 ScriptRuntimeException 異常。

MoonSharp 類型到 CLR 類型的受限自動轉換

非常感謝您提供這些關于 MoonSharp 類型轉換的詳細信息!我來總結一下要點:

MoonSharp 類型到 CLR 類型的受限自動轉換比默認轉換要復雜得多。它發生在需要將 MoonSharp 值存儲到給定類型的 CLR 變量中的情況下,轉換方式幾乎有無限多種。

特殊情況:

  • 如果目標類型是 DynValue,則不進行轉換,返回原始值。
  • 如果目標類型是 object,則應用默認轉換。
  • 如果要映射 nil 值,則 null 映射到引用類型和可空值類型。某些情況下會嘗試匹配默認值。否則拋出異常。
  • 如果沒有提供值,則盡可能使用默認值。

數據類型轉換:

  • 字符串可轉換為 String, StringBuilder 或 Char
  • 布爾值可轉換為 Boolean 及其可空版本,也可轉換為字符串類型
  • 數字可轉換為 SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Decimal, Double 及其可空版本,也可轉換為字符串類型
  • 函數轉換為 Closure, ScriptFunctionDelegate, ClrFunction 或 Func 委托
  • 非靜態的 userdata 如果類型兼容則可轉換。也可通過 ToString() 轉換為字符串類型
  • 表可轉換為 Table, Dictionary, List, 數組等多種集合類型,但轉換到泛型和類型化數組有一些限制,可能會有性能和兼容性問題

總之,MoonSharp 在類型轉換上非常靈活,但復雜類型的轉換可能存在一些問題。必要時可以添加自定義轉換器來解決。在面向 AOT 平臺時,要特別小心值類型的泛型可能引入的不兼容問題。

end

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/72898.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/72898.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/72898.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ROS云課三分鐘-差動移動機器人導航報告如何撰寫-及格邊緣瘋狂試探

提示詞&#xff1a;基于如上所有案例并結合roslaunch teb_local_planner_tutorials robot_diff_drive_in_stage.launch和上面所有對話內容&#xff0c;設計一個差速移動機器人仿真實驗&#xff0c;并完成報告的全文撰寫。 差速移動機器人導航仿真實驗報告 一、實驗目的 驗證 T…

ACE協議學習1

在多核系統或復雜SoC&#xff08;System on Chip&#xff09;中&#xff0c;不同處理器核心或IP&#xff08;Intellectual Property&#xff09;模塊之間需要保持數據的一致性。常用的是ACE協議or CHI。 先對ACE協議進行學習 ACE協議&#xff08;Advanced Microcontroller Bu…

ajax之生成一個ajax的demo示例

目錄 一. node.js和express ?二. 使用express創建后端服務 三. 創建前端 一. node.js和express ajax是前端在不刷新的情況下訪問后端的技術&#xff0c;所以首先需要配置一個后端服務&#xff0c;可以使用node.js和express。 首先生成一個空項目&#xff0c;新建main目錄…

Java 字節碼操縱框架 -ASM

Java 字節碼操縱框架 -ASM 1.ASM 概述: ASM 是用于 Java 字節碼操縱的框架,可動態生成新類或增強現有類的功能。它既能直接產生二進制 class 文件,也能在類被加載到虛擬機之前動態改變類行為,通過讀取類文件信息來分析、修改類行為,甚至生成新類。許多流行框架如 cglib、…

kafka + flink +mysql 案例

假設你有兩個Kafka主題&#xff1a;user_activities_topic 和 product_views_topic&#xff0c;并且你希望將user_activities_topic中的數據寫入到user_activities表&#xff0c;而將product_views_topic中的數據寫入到product_views表。 maven <dependencies><!-- …

遠程登錄客戶端軟件 CTerm 發布了 v4.0.0

有時候我們需要遠程登錄到 Linux/Unix 服務器&#xff0c;這方面使用最廣泛的客戶端軟件是 PuTTY&#xff0c;不過它是全英文的&#xff0c;而且是單窗口的&#xff0c;有時候顯得不那么方便。 CTerm (Clever Terminal) 是一個 Windows 平臺下支持 Telnet 和 SSH 協議進行遠程…

從李佳琦團隊看新型用工:靈活就業如何重構組織架構?

2022年“雙11”期間&#xff0c;李佳琦直播間累計銷售額突破115億元&#xff08;來源&#xff1a;新腕數據《2022雙11直播電商戰報》&#xff09;&#xff0c;其背后團隊規模約400人&#xff0c;但全職員工僅占35%&#xff0c;其余65%為外包選品團隊、兼職客服、第三方MCN機構人…

微軟程序的打包格式MSIX

MSIX 微軟推出的MSIX格式是其為統一Windows應用程序打包和部署而設計的新一代安裝包格式&#xff0c;具有以下核心特點和進展&#xff1a; 1. 推出背景與時間線 MSIX最初于2018年在微軟Build大會上宣布&#xff0c;并在同年7月發布預覽版打包工具&#xff0c;10月正式版上線…

AFL++安裝

學習fuzzing也幾天了&#xff0c;今天記錄AFL的安裝及使用 一、實驗環境 虛擬機&#xff1a;ubuntu20.04 當然也可以uname -a去看自己的版本號 二、AFL安裝 1.先更新一下工具 sudo apt update2.安裝AFL必要的一些依賴&#xff0c;例如編譯工具&#xff08;如 build-essen…

【STM32】ADC功能-單通道多通道(學習筆記)

本章結合上一節內容復習更好理解【江協科技STM32】ADC數模轉換器-學習筆記-CSDN博客 一、ADC單通道 接線圖 ADC初始化 ①RCC開啟時鐘&#xff0c;包括ADC和GPIO的時鐘&#xff0c;另外ADCCLK的分頻器也要配置 ②配置GPIO,&#xff0c;把需要用的GPIO配置成模擬輸入模式&am…

基于YOLO11深度學習的運動品牌LOGO檢測與識別系統【python源碼+Pyqt5界面+數據集+訓練代碼】

《------往期經典推薦------》 一、AI應用軟件開發實戰專欄【鏈接】 項目名稱項目名稱1.【人臉識別與管理系統開發】2.【車牌識別與自動收費管理系統開發】3.【手勢識別系統開發】4.【人臉面部活體檢測系統開發】5.【圖片風格快速遷移軟件開發】6.【人臉表表情識別系統】7.【…

當前主流的大模型訓練與推理框架的全面匯總

以下是當前主流的大模型訓練與推理框架的全面匯總 以下是更新后包含 SGLang 的大模型訓練與推理框架列表&#xff0c;并對分類和示例進行了優化&#xff1a; 一、通用深度學習推理框架 TensorRT-LLM 特點&#xff1a;NVIDIA推出的針對Transformer類模型的優化框架&#xff0c;支…

Linux學習(八)(服務管理(檢查服務狀態,開始/停止服務,檢查服務日志,創建新服務))

服務管理 Linux 中的服務管理是指控制 Linux 在啟動和關閉計算機的過程中啟動和停止的服務&#xff08;或“守護程序”&#xff09;的系統。這些服務執行各種功能&#xff0c;并提供未附加到用戶界面的進程。 Linux 系統&#xff0c;尤其是系統管理員&#xff0c;通常需要管理…

ElasticSearch 分詞器介紹及測試:Standard(標準分詞器)、English(英文分詞器)、Chinese(中文分詞器)、IK(IK 分詞器)

ElasticSearch 分詞器介紹及測試&#xff1a;Standard&#xff08;標準分詞器&#xff09;、English&#xff08;英文分詞器&#xff09;、Chinese&#xff08;中文分詞器&#xff09;、IK&#xff08;IK 分詞器&#xff09; ElasticSearch 分詞器介紹及測試1. Standard Analyz…

【計算機網絡】確認家庭網絡是千兆/百兆帶寬并排查問題

要確認你的帶寬是千兆&#xff08;1000Mbps&#xff09;還是百兆&#xff08;100Mbps&#xff09;&#xff0c;可以通過以下方法逐步排查&#xff1a; 一、檢查物理設備 1. 查看路由器和光貓的網口 千兆網口&#xff1a;路由器或光貓的網口旁通常會標注 “10/100/1000M” 或 …

[數據分享第七彈]全球洪水相關數據集

洪水是一種常見的自然災害&#xff0c;在全球范圍內造成了極為嚴重的威脅。近年來&#xff0c;針對洪水事件的檢測分析&#xff0c;以及對于洪水災害和災后恢復能力的研究日漸增多&#xff0c;也產生了眾多洪水數據集。今天&#xff0c;我們一起來收集整理一下相關數據集。&…

深入探討AI-Ops架構 第一講 - 運維的進化歷程以及未來發展趨勢

首先&#xff0c;讓我們一起回顧運維的進化之路&#xff0c;然后再深入探討AI-Ops架構的細節。 運維的進化歷程 1. AI 大范圍普及前的運維狀態 (傳統運維) 在AI技術尚未廣泛滲透到運維領域之前&#xff0c;我們稱之為傳統運維&#xff0c;其主要特點是&#xff1a; 人工驅動…

Hive-數據傾斜優化

數據傾斜的原因 1&#xff09;key分布不均勻&#xff0c;本質上就是業務數據有可能會存在傾斜 2&#xff09;某些SQL語句本身就有數據傾斜 關鍵詞 情形 后果 Join A、其中一個表較小&#xff0c;但是key集中; B、兩張表都是大表&#xff0c;key不均 分發到…

番外篇 - Docker的使用

一、Docker的介紹 Docker 是一個開源的應用容器引擎&#xff0c;基于 Go 語言 并遵從Apache2.0協議開源。 Docker 可以讓開發者打包他們的應用以及依賴包到一個輕量級、可移植的容器中&#xff0c;然后發布到任何流行的 Linux 機器上&#xff0c;也可以實現虛擬化。 容器是完…

深度學習與普通神經網絡有何區別?

深度學習與普通神經網絡的主要區別體現在以下幾個方面&#xff1a; 一、結構復雜度 普通神經網絡&#xff1a;通常指淺層結構&#xff0c;層數較少&#xff0c;一般為2-3層&#xff0c;包括輸入層、一個或多個隱藏層、輸出層。深度學習&#xff1a;強調通過5層以上的深度架構…