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) 的关系如下:
WebAssembly 运行时:
wasmtime是一个运行时,它允许你在本地环境中执行 WebAssembly 代码,而不需要浏览器。这意味着你可以使用wasmtime运行任何编译为 WASM 的代码,无论是从 C、Rust、Go 还是其他语言编译的。支持 WASI:
wasmtime是 WASI 的一个主要实现,这意味着它可以运行那些使用 WASI 接口的 WebAssembly 程序,从而让这些程序可以访问文件、网络和其他系统资源。安全性: 与 WebAssembly 一样,
wasmtime也提供了一个沙盒环境,确保 WASM 代码在受限制的环境中运行,从而提供了一定的安全性。跨平台:
wasmtime可以在多种操作系统和平台上运行,包括 Windows、Linux 和 macOS。高效:
wasmtime使用了先进的即时编译 (JIT) 技术,确保 WebAssembly 代码能够高效地执行。
总之,wasmtime 是一个与 WebAssembly 紧密相关的运行时,它允许开发者在非浏览器环境中执行 WASM 代码,并提供了对 WASI 的支持,从而扩展了 WebAssembly 的能力和应用范围。
准备工作
环境
请先安装wasi在https://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 的关键点:
可读性: 虽然 WASM 二进制格式是为机器设计的,但 WAT 格式是为人类设计的。它提供了一种更加可读和可编辑的方式来表示 WebAssembly 代码。
结构: WAT 代码通常包含一系列的指令、函数定义和其他模块级声明。它的语法是 S-expression,这是一种用于表示嵌套结构的简单文本格式。
转换: 你可以使用工具,如
wasm2wat和wat2wasm,来在 WAT 和 WASM 之间进行转换。这意味着你可以手动编写或修改 WAT 代码,然后将其编译为 WASM 二进制格式,或者从现有的 WASM 代码反编译为 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的案例。
执行项目

如何执行其他语言的wasm?
Rust 编译 WebAssembly 指南 - 知乎 (zhihu.com)
可以参考这个博客,使用将rust编译成wasm,然后在编译成wat格式。
技术交流
qq技术交流群:737776595
更多技术分享关注token的技术分享公众号

c#如何使用WASM跨语言调用?的更多相关文章
- Atitit java c# php c++ js跨语言调用matlab实现边缘检测等功能attilax总结
Atitit java c# php c++ js跨语言调用matlab实现边缘检测等功能attilax总结 1.1. 边缘检测的基本方法Canny最常用了1 1.2. 编写matlab边缘检测代码, ...
- Golang通过Thrift框架完美实现跨语言调用
每种语言都有自己最擅长的领域,Golang 最适合的领域就是服务器端程序. 做为服务器端程序,需要考虑性能同时也要考虑与各种语言之间方便的通讯.采用http协议简单,但性能不高.采用TCP通讯,则需要 ...
- Golang、Php、Python、Java基于Thrift0.9.1实现跨语言调用
目录: 一.什么是Thrift? 1) Thrift内部框架一瞥 2) 支持的数据传输格式.数据传输方式和服务模型 3) Thrift IDL 二.Thrift的官方网站在哪里? 三.在哪里下载?需要 ...
- 跨语言调用Hangfire定时作业服务
跨语言调用Hangfire定时作业服务 背景 Hangfire允许您以非常简单但可靠的方式执行后台定时任务的工作.内置对任务的可视化操作.非常方便. 但令人遗憾的是普遍都是业务代码和hagnfire服 ...
- C++ 跨语言调用 Java
C++ 跨语言调用 Java Java JDK 提供了 JNI 接口供 C/C++ 程序调用 Java 编译后的类与方法,主要依赖于头文件(jni.h) 和 动态库(jvm.so/jvm.dll),由 ...
- 使用thrift进行跨语言调用(php c# java)
使用thrift进行跨语言调用(php c# java) 1:前言 实际上本文说的是跨进程的异构语言调用,举个简单的例子就是利用PHP写的代码去调C#或是java写的服务端.其实除了本文提供的办法 ...
- vs2019 Com组件初探-简单的COM编写以及实现跨语言调用
前提条件 1.掌握C++基础语法 2.平台安装 vs2019 3.本地平台为 windows 10 1909 X64 4.了解vbs基础语法 本次目标 1.掌握Com组件的概念及原理 2.编写一个简单 ...
- Java跨语言调用,使用JNA访问Java外部接口
1. JNA简单介绍 先说JNI(Java Native Interface)吧,有过不同语言间通信经历的一般都知道,它允许Java代码和其他语言(尤其C/C++)写的代码进行交互,只要遵守调用约定即 ...
- CLS(公共语言规范)的CLSCompliant(跨语言调用)
.net的一个很重要的特性就是跨语言的编程,用C#写的dll可以在VB.net里调用,例如:用C#写的一个类,编译到dll中,然后在VB.net中调用: using System;namespace ...
- 跨语言调用C#代码的新方式-DllExport
简介 上一篇文章使用C#编写一个.NET分析器文章发布以后,很多小伙伴都对最新的NativeAOT函数导出比较感兴趣,今天故写一篇短文来介绍一下如何使用它. 在以前,如果有其他语言需要调用C#编写的库 ...
随机推荐
- python爬虫防止IP被封的一些措施(转)
python爬虫防止IP被封的一些措施(转) 在编写爬虫爬取数据的时候,因为很多网站都有反爬虫措施,所以很容易被封IP,就不能继续爬了.在爬取大数据量的数据时更是瑟瑟发抖,时刻担心着下一秒IP可能就被 ...
- 系统MySQL服务无法启动报错1067的四种解决方法win7系统MySQL服务无法启动报错1067的四种解决方法
有些win7系统用户在登陆mysql或者重装mysql时出现"无法启动MYSQL服务,错误1067",而且重启.修复注册表都没办法解决问题.那么遇到MySQL服务无法启动问 ...
- 美女同事的烦恼:如何配置 Apache SkyWalking 告警?
小婉 技术部基本上是一个和尚庙,女生非常少,即使有女生也略微有点抽象,小婉就不一样,她气质绝佳. 上午,同事小婉刚才从老板办公室里出来,看上去一脸不悦的样子.为了表示对同事的关(ba)心(gua),我 ...
- Spring Boot 3.1中如何整合Spring Security和Keycloak
在今年2月14日的时候,Keycloak 团队宣布他们正在弃用大多数 Keycloak 适配器.其中包括Spring Security和Spring Boot的适配器,这意味着今后Keycloak团队 ...
- shader编程经典:分形--科赫曲线
序言 科赫(雪花)曲线是一个经典分形图案,来一起领略下分形之美.本篇内容用到一些基础的内容,例如UV的理解和画线技巧,有需要的话可以参考合集的画圆和画线两篇文章. 示例 shadertoy 代码: # ...
- Vue——属性指令、style和class、条件渲染、列表渲染、事件处理、数据双向绑定、过滤案例
vm对象 <body> <div id="app"> <h1>{{name}}</h1> <button @click=&qu ...
- 2023-06-03:redis中pipeline有什么好处,为什么要用 pipeline?
2023-06-03:redis中pipeline有什么好处,为什么要用 pipeline? 答案2023-06-03: Redis客户端执行一条命令通常包括以下四个阶段: 1.发送命令:客户端将要执 ...
- PE 结构的三种地址
三种地址 (一)VA(虚拟地址):PE 文件被 Windows 加载到内存后的地址. (二) RVA(相对虚拟地址):PE 文件虚拟地址相对于映射基地址(对于 EXE 文件来说,映射基地址是 ...
- 自然语言处理 Paddle NLP - 文本语义相似度计算(ERNIE-Gram)
基于预训练模型 ERNIE-Gram 实现语义匹配 1. 背景介绍 文本语义匹配任务,简单来说就是给定两段文本,让模型来判断两段文本是不是语义相似. 在本案例中以权威的语义匹配数据集 LCQMC 为例 ...
- 做副业的我很迷茫,但ChatGPT却治好了我——AI从业者被AI模型治愈的故事
迷茫,无非就是不知道自己要做什么,没有目标,没有方向. 当有一个明确的目标时,往往干劲十足.但做副业过程中,最大的问题往往就是 不知道自己该干什么. 干什么?怎么干?干到什么程度?这是做副业(甚至任何 ...