C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C# WASM跨语言调用

详解C#如何使用WASM跨语言调用

作者:tokengo

WebAssembly(简称Wasm)是一种用于基于堆栈的虚拟机的二进制指令格式,这篇文章主要介绍了C#如何使用WASM跨语言调用,需要的小伙伴可以了解一下

介绍Wasm(WebAssembly)

WebAssembly(简称Wasm)是一种用于基于堆栈的虚拟机的二进制指令格式。Wasm被设计为编程语言的可移植编译目标,支持在web上部署客户端和服务器应用程序。

什么是wasmtime (WebAssembly Time)?它和WASM(WebAssembly)是什么关系?

wasmtime 是一个独立的、轻量级的 WebAssembly (WASM) 运行时,它支持 WASI (WebAssembly System Interface)。wasmtime 由 Bytecode Alliance 开发,该联盟致力于创建新的软件基础设施,使得模块化、可组合、安全和高效的软件成为可能。

wasmtime 和 WASM (WebAssembly) 的关系如下:

总之,wasmtime 是一个与 WebAssembly 紧密相关的运行时,它允许开发者在非浏览器环境中执行 WASM 代码,并提供了对 WASI 的支持,从而扩展了 WebAssembly 的能力和应用范围。

准备工作

环境

请先安装wasihttps://github.com/bytecodealliance/wasmtime/releases中找到适合的操作系统下载wsmi

安装完成以后在cmd中执行即可查看是否安装成功

wasmtime

效果如图。

创建一个控制台项目

创建一个ConsoleApp2的控制台项目

添加NuGet包。

<ItemGroup>
      <PackageReference Include="Wasi.Sdk" Version="0.1.4-preview.10020" />
</ItemGroup>

Wasi.Sdk是用于生成.wasm文件的sdk,仓库地址:https://github.com/dotnet/dotnet-wasi-sdk

当我们右键项目的适合点击生成则会在当前项目的bin/Debug|Release文件夹下面生成一个{项目名称}.wasm的文件,当然还包括了.dll文件。

生成.wasm文件

选中我们的项目,右键重新生成

然后右键项目,在文件资源管理器中打开文件夹。

依次打开bin=>Release|Debug=>net7.0(看选择的SDK)

在当前路径打开控制台。然后使用wasmtim执行wasm文件。

wasmtime ConsoleApp2.wasm

就这样完成了简单的wasm使用。使用c#编译成wasm的格式,然后执行。

执行wat

什么是wat

WAT (WebAssembly Text Format) 是 WebAssembly 的文本表示形式。当我们谈论 WebAssembly (WASM),我们通常指的是其二进制格式,这是一种为浏览器和其他宿主环境设计的低级虚拟机代码。然而,为了方便人类阅读和编写,WASM 也有一个等效的文本格式,即 WAT。

以下是一些关于 WAT 的关键点:

示例: 下面是一个简单的 WAT 示例,该示例定义了一个函数,该函数接受两个整数参数并返回它们的和:

(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 的文本表示形式,它为开发者提供了一种更加直观和可读的方式来查看、编写或修改 WebAssembly 代码。

在当前解决方案中在创建一个项目

创建一个ConsoleApp1的控制台项目

在项目中添加一下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))
  )
)

设置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)}");

这里提供了一个使用c#调用test.wat的案例。

执行项目

到此这篇关于详解C#如何使用WASM跨语言调用的文章就介绍到这了,更多相关C# WASM跨语言调用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文