詳解C#如何使用WASM跨語(yǔ)言調(diào)用
介紹Wasm(WebAssembly)
WebAssembly(簡(jiǎn)稱Wasm)是一種用于基于堆棧的虛擬機(jī)的二進(jìn)制指令格式。Wasm被設(shè)計(jì)為編程語(yǔ)言的可移植編譯目標(biāo),支持在web上部署客戶端和服務(wù)器應(yīng)用程序。
什么是wasmtime (WebAssembly Time)?它和WASM(WebAssembly)是什么關(guān)系?
wasmtime
是一個(gè)獨(dú)立的、輕量級(jí)的 WebAssembly (WASM) 運(yùn)行時(shí),它支持 WASI (WebAssembly System Interface)。wasmtime
由 Bytecode Alliance 開(kāi)發(fā),該聯(lián)盟致力于創(chuàng)建新的軟件基礎(chǔ)設(shè)施,使得模塊化、可組合、安全和高效的軟件成為可能。
wasmtime
和 WASM (WebAssembly) 的關(guān)系如下:
- WebAssembly 運(yùn)行時(shí):
wasmtime
是一個(gè)運(yùn)行時(shí),它允許你在本地環(huán)境中執(zhí)行 WebAssembly 代碼,而不需要瀏覽器。這意味著你可以使用wasmtime
運(yùn)行任何編譯為 WASM 的代碼,無(wú)論是從 C、Rust、Go 還是其他語(yǔ)言編譯的。 - 支持 WASI:
wasmtime
是 WASI 的一個(gè)主要實(shí)現(xiàn),這意味著它可以運(yùn)行那些使用 WASI 接口的 WebAssembly 程序,從而讓這些程序可以訪問(wèn)文件、網(wǎng)絡(luò)和其他系統(tǒng)資源。 - 安全性: 與 WebAssembly 一樣,
wasmtime
也提供了一個(gè)沙盒環(huán)境,確保 WASM 代碼在受限制的環(huán)境中運(yùn)行,從而提供了一定的安全性。 - 跨平臺(tái):
wasmtime
可以在多種操作系統(tǒng)和平臺(tái)上運(yùn)行,包括 Windows、Linux 和 macOS。 - 高效:
wasmtime
使用了先進(jìn)的即時(shí)編譯 (JIT) 技術(shù),確保 WebAssembly 代碼能夠高效地執(zhí)行。
總之,wasmtime
是一個(gè)與 WebAssembly 緊密相關(guān)的運(yùn)行時(shí),它允許開(kāi)發(fā)者在非瀏覽器環(huán)境中執(zhí)行 WASM 代碼,并提供了對(duì) WASI 的支持,從而擴(kuò)展了 WebAssembly 的能力和應(yīng)用范圍。
準(zhǔn)備工作
環(huán)境
請(qǐng)先安裝wasi
在https://github.com/bytecodealliance/wasmtime/releases
中找到適合的操作系統(tǒng)下載wsmi
安裝完成以后在cmd
中執(zhí)行即可查看是否安裝成功
wasmtime
效果如圖。
創(chuàng)建一個(gè)控制臺(tái)項(xiàng)目
創(chuàng)建一個(gè)ConsoleApp2
的控制臺(tái)項(xiàng)目
添加NuGet包。
<ItemGroup> <PackageReference Include="Wasi.Sdk" Version="0.1.4-preview.10020" /> </ItemGroup>
Wasi.Sdk
是用于生成.wasm
文件的sdk,倉(cāng)庫(kù)地址:https://github.com/dotnet/dotnet-wasi-sdk
當(dāng)我們右鍵項(xiàng)目的適合點(diǎn)擊生成則會(huì)在當(dāng)前項(xiàng)目的bin/Debug|Release
文件夾下面生成一個(gè){項(xiàng)目名稱}.wasm
的文件,當(dāng)然還包括了.dll
文件。
生成.wasm文件
選中我們的項(xiàng)目,右鍵重新生成
。
然后右鍵項(xiàng)目,在文件資源管理器中打開(kāi)文件夾。
依次打開(kāi)bin
=>Release|Debug
=>net7.0(看選擇的SDK)
在當(dāng)前路徑打開(kāi)控制臺(tái)
。然后使用wasmtim
執(zhí)行wasm文件。
wasmtime ConsoleApp2.wasm
就這樣完成了簡(jiǎn)單的wasm使用。使用c#編譯成wasm的格式,然后執(zhí)行。
執(zhí)行wat
什么是wat
WAT (WebAssembly Text Format) 是 WebAssembly 的文本表示形式。當(dāng)我們談?wù)?WebAssembly (WASM),我們通常指的是其二進(jìn)制格式,這是一種為瀏覽器和其他宿主環(huán)境設(shè)計(jì)的低級(jí)虛擬機(jī)代碼。然而,為了方便人類閱讀和編寫(xiě),WASM 也有一個(gè)等效的文本格式,即 WAT。
以下是一些關(guān)于 WAT 的關(guān)鍵點(diǎn):
- 可讀性: 雖然 WASM 二進(jìn)制格式是為機(jī)器設(shè)計(jì)的,但 WAT 格式是為人類設(shè)計(jì)的。它提供了一種更加可讀和可編輯的方式來(lái)表示 WebAssembly 代碼。
- 結(jié)構(gòu): WAT 代碼通常包含一系列的指令、函數(shù)定義和其他模塊級(jí)聲明。它的語(yǔ)法是 S-expression,這是一種用于表示嵌套結(jié)構(gòu)的簡(jiǎn)單文本格式。
- 轉(zhuǎn)換: 你可以使用工具,如
wasm2wat
和wat2wasm
,來(lái)在 WAT 和 WASM 之間進(jìn)行轉(zhuǎn)換。這意味著你可以手動(dòng)編寫(xiě)或修改 WAT 代碼,然后將其編譯為 WASM 二進(jìn)制格式,或者從現(xiàn)有的 WASM 代碼反編譯為 WAT 格式。
示例: 下面是一個(gè)簡(jiǎn)單的 WAT 示例,該示例定義了一個(gè)函數(shù),該函數(shù)接受兩個(gè)整數(shù)參數(shù)并返回它們的和:
(module (func $add (param $a i32) (param $b i32) (result i32) get_local $a get_local $b i32.add) (export "add" (func $add)) )
總的來(lái)說(shuō),WAT 是 WebAssembly 的文本表示形式,它為開(kāi)發(fā)者提供了一種更加直觀和可讀的方式來(lái)查看、編寫(xiě)或修改 WebAssembly 代碼。
在當(dāng)前解決方案中在創(chuàng)建一個(gè)項(xiàng)目
創(chuàng)建一個(gè)ConsoleApp1
的控制臺(tái)項(xiàng)目
在項(xiàng)目中添加一下nuget包
<ItemGroup> <PackageReference Include="wasmtime" Version="11.0.1" /> </ItemGroup>
官方倉(cāng)庫(kù):https://github.com/bytecodealliance/wasmtime-dotnet
然后新增test.wat
文件,寫(xiě)入一下代碼,以下代碼則是WAT
代碼。
(module (import "" "table" (table $t 4 funcref)) (func (export "call_indirect") (param i32 i32 i32) (result i32) (call_indirect $t (param i32 i32) (result i32) (local.get 1) (local.get 2) (local.get 0)) ) )
設(shè)置test.wat
文件屬性
打開(kāi)Program.cs
文件,修改代碼
using Wasmtime; using var engine = new Engine(); using var module = Module.FromTextFile(engine, "test.wat"); using var linker = new Linker(engine); using var store = new Store(engine); var table = new Table(store, TableKind.FuncRef, null, 4); table.SetElement(0, Function.FromCallback(store, (int a, int b) => a + b)); table.SetElement(1, Function.FromCallback(store, (int a, int b) => a - b)); table.SetElement(2, Function.FromCallback(store, (int a, int b) => a * b)); table.SetElement(3, Function.FromCallback(store, (int a, int b) => a / b)); linker.Define("", "table", table); var instance = linker.Instantiate(store, module); var call_indirect = instance.GetFunction<int, int, int, int>("call_indirect"); if (call_indirect is null) { Console.WriteLine("error: `call_indirect` export is missing"); return; } Console.WriteLine($"100 + 25 = {call_indirect(0, 100, 25)}"); Console.WriteLine($"100 - 25 = {call_indirect(1, 100, 25)}"); Console.WriteLine($"100 * 25 = {call_indirect(2, 100, 25)}"); Console.WriteLine($"100 / 25 = {call_indirect(3, 100, 25)}");
這里提供了一個(gè)使用c#調(diào)用test.wat
的案例。
執(zhí)行項(xiàng)目
到此這篇關(guān)于詳解C#如何使用WASM跨語(yǔ)言調(diào)用的文章就介紹到這了,更多相關(guān)C# WASM跨語(yǔ)言調(diào)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#中實(shí)現(xiàn)任意List的全組合算法代碼
這篇文章主要是介紹了.net C# 實(shí)現(xiàn)任意List的全組合算法實(shí)現(xiàn)代碼,需要的朋友可以參考下2013-05-05淺析C#中數(shù)組,ArrayList與List對(duì)象的區(qū)別
在C#中,當(dāng)我們想要存儲(chǔ)一組對(duì)象的時(shí)候,就會(huì)想到用數(shù)組,ArrayList,List這三個(gè)對(duì)象了。那么這三者到底有什么樣的區(qū)別呢2013-07-07C#禁止textbox復(fù)制、粘貼、剪切及鼠標(biāo)右鍵的方法
這篇文章主要介紹了C#禁止textbox復(fù)制、粘貼、剪切及鼠標(biāo)右鍵的方法,涉及C#針對(duì)窗口消息的處理技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-09-09C# 通過(guò)Socket讀取大量數(shù)據(jù)的示例
這篇文章主要介紹了C# 通過(guò)Socket讀取大量數(shù)據(jù)的示例,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下2021-03-03