詳解C#如何使用WASM跨語言調(diào)用
介紹Wasm(WebAssembly)
WebAssembly(簡稱Wasm)是一種用于基于堆棧的虛擬機(jī)的二進(jìn)制指令格式。Wasm被設(shè)計(jì)為編程語言的可移植編譯目標(biāo),支持在web上部署客戶端和服務(wù)器應(yīng)用程序。
什么是wasmtime (WebAssembly Time)?它和WASM(WebAssembly)是什么關(guān)系?
wasmtime 是一個(gè)獨(dú)立的、輕量級的 WebAssembly (WASM) 運(yùn)行時(shí),它支持 WASI (WebAssembly System Interface)。wasmtime 由 Bytecode Alliance 開發(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 的代碼,無論是從 C、Rust、Go 還是其他語言編譯的。 - 支持 WASI:
wasmtime是 WASI 的一個(gè)主要實(shí)現(xiàn),這意味著它可以運(yùn)行那些使用 WASI 接口的 WebAssembly 程序,從而讓這些程序可以訪問文件、網(wǎng)絡(luò)和其他系統(tǒng)資源。 - 安全性: 與 WebAssembly 一樣,
wasmtime也提供了一個(gè)沙盒環(huán)境,確保 WASM 代碼在受限制的環(huán)境中運(yùn)行,從而提供了一定的安全性。 - 跨平臺:
wasmtime可以在多種操作系統(tǒng)和平臺上運(yùn)行,包括 Windows、Linux 和 macOS。 - 高效:
wasmtime使用了先進(jìn)的即時(shí)編譯 (JIT) 技術(shù),確保 WebAssembly 代碼能夠高效地執(zhí)行。
總之,wasmtime 是一個(gè)與 WebAssembly 緊密相關(guān)的運(yùn)行時(shí),它允許開發(fā)者在非瀏覽器環(huán)境中執(zhí)行 WASM 代碼,并提供了對 WASI 的支持,從而擴(kuò)展了 WebAssembly 的能力和應(yīng)用范圍。
準(zhǔn)備工作
環(huán)境
請先安裝wasi在https://github.com/bytecodealliance/wasmtime/releases中找到適合的操作系統(tǒng)下載wsmi
安裝完成以后在cmd中執(zhí)行即可查看是否安裝成功
wasmtime

效果如圖。
創(chuàng)建一個(gè)控制臺項(xiàng)目
創(chuàng)建一個(gè)ConsoleApp2的控制臺項(xiàng)目

添加NuGet包。
<ItemGroup>
<PackageReference Include="Wasi.Sdk" Version="0.1.4-preview.10020" />
</ItemGroup>Wasi.Sdk是用于生成.wasm文件的sdk,倉庫地址:https://github.com/dotnet/dotnet-wasi-sdk
當(dāng)我們右鍵項(xiàng)目的適合點(diǎn)擊生成則會在當(dāng)前項(xiàng)目的bin/Debug|Release文件夾下面生成一個(gè){項(xiàng)目名稱}.wasm的文件,當(dāng)然還包括了.dll文件。
生成.wasm文件
選中我們的項(xiàng)目,右鍵重新生成。
然后右鍵項(xiàng)目,在文件資源管理器中打開文件夾。

依次打開bin=>Release|Debug=>net7.0(看選擇的SDK)
在當(dāng)前路徑打開控制臺。然后使用wasmtim執(zhí)行wasm文件。
wasmtime ConsoleApp2.wasm

就這樣完成了簡單的wasm使用。使用c#編譯成wasm的格式,然后執(zhí)行。
執(zhí)行wat
什么是wat
WAT (WebAssembly Text Format) 是 WebAssembly 的文本表示形式。當(dāng)我們談?wù)?WebAssembly (WASM),我們通常指的是其二進(jìn)制格式,這是一種為瀏覽器和其他宿主環(huán)境設(shè)計(jì)的低級虛擬機(jī)代碼。然而,為了方便人類閱讀和編寫,WASM 也有一個(gè)等效的文本格式,即 WAT。
以下是一些關(guān)于 WAT 的關(guān)鍵點(diǎn):
- 可讀性: 雖然 WASM 二進(jìn)制格式是為機(jī)器設(shè)計(jì)的,但 WAT 格式是為人類設(shè)計(jì)的。它提供了一種更加可讀和可編輯的方式來表示 WebAssembly 代碼。
- 結(jié)構(gòu): WAT 代碼通常包含一系列的指令、函數(shù)定義和其他模塊級聲明。它的語法是 S-expression,這是一種用于表示嵌套結(jié)構(gòu)的簡單文本格式。
- 轉(zhuǎn)換: 你可以使用工具,如
wasm2wat和wat2wasm,來在 WAT 和 WASM 之間進(jìn)行轉(zhuǎn)換。這意味著你可以手動編寫或修改 WAT 代碼,然后將其編譯為 WASM 二進(jìn)制格式,或者從現(xiàn)有的 WASM 代碼反編譯為 WAT 格式。
示例: 下面是一個(gè)簡單的 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))
)總的來說,WAT 是 WebAssembly 的文本表示形式,它為開發(fā)者提供了一種更加直觀和可讀的方式來查看、編寫或修改 WebAssembly 代碼。
在當(dāng)前解決方案中在創(chuàng)建一個(gè)項(xiàng)目
創(chuàng)建一個(gè)ConsoleApp1的控制臺項(xiàng)目

在項(xiàng)目中添加一下nuget包
<ItemGroup>
<PackageReference Include="wasmtime" Version="11.0.1" />
</ItemGroup>官方倉庫:https://github.com/bytecodealliance/wasmtime-dotnet
然后新增test.wat文件,寫入一下代碼,以下代碼則是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文件屬性

打開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跨語言調(diào)用的文章就介紹到這了,更多相關(guān)C# WASM跨語言調(diào)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#程序員應(yīng)該養(yǎng)成的程序性能優(yōu)化寫法
工作和生活中經(jīng)??梢钥吹揭恍┏绦蛟?寫代碼的時(shí)候只關(guān)注代碼的邏輯性,而不考慮運(yùn)行效率,其實(shí)這對大多數(shù)程序猿來說都是沒有問題的,不過作為一只有理想的CodeMonkey,我還是希望給大家分享一些性能優(yōu)化心得2017-08-08
c#之System.OutOfMemoryException解讀
System.OutOfMemoryException是C#中的內(nèi)存分配異常,常見原因包括內(nèi)存不足、內(nèi)存泄漏等,解決辦法有優(yōu)化內(nèi)存使用、增加可用內(nèi)存、優(yōu)化算法和數(shù)據(jù)結(jié)構(gòu)等,注意,此異常通常由程序設(shè)計(jì)或資源管理問題引起,需合理管理內(nèi)存資源2026-04-04
C#使用StackExchange.Redis實(shí)現(xiàn)分布式鎖的兩種方式介紹
分布式鎖在集群的架構(gòu)中發(fā)揮著重要的作用,這篇文章主要為大家介紹了C#使用StackExchange.Redis實(shí)現(xiàn)分布式鎖的兩種方式,希望對大家有一定的幫助2025-04-04
C#創(chuàng)建Windows服務(wù)的圖文教程
本文主要介紹了C#創(chuàng)建Windows服務(wù)的圖文教程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
C#難點(diǎn)逐個(gè)擊破(2):out返回參數(shù)
之前提到ref是將原方法中的參數(shù)影響的結(jié)果返回到調(diào)用它的方法中,out與ref類似,相比之下,ref傳遞參數(shù)的地址,out是返回值。2010-02-02
C#中實(shí)現(xiàn)插入、刪除Excel分頁符的方法
這篇文章主要給大家介紹了關(guān)于在C#中實(shí)現(xiàn)插入、刪除Excel分頁符的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-05-05

