WASM学习笔记

WebAssembly概念

webassembly是一种运行在现代web浏览器中的新型代码,不仅提供新的性能特性,同时还在性能方面有着巨大提升。它的涉及本意并非是提供开发者直接编译的代码,而是为诸如C,C++和Rust等源语言提供的一个有效的编译目标。

简单来说,你可以使用C,C++,Rust,Go等语言编写代码,然后编译为WebAssembly,在浏览器中运行。

编译C/C++为WebAssembly

Emscripten环境安装
所需条件
  • python
  • git
安装步骤
  1. 打开cmd,进入到软件将会安装到的目录下
  2. 输入 git clone https://github.com/emscripten-core/emsdk.git
  3. 输入 cd emsdk
  4. 输入 emsdk install latest
  5. 配置系统环境变量,依据下图操作

打开编译系统环境变量窗口,点击环境变量

最后一直点击每个未关闭窗口的确认即可。

具体使用

使用cmd打开需要被编译的C++文件夹,输入命令行emsdk activate (这仅仅会激活当前的环境,下次换另一个文件夹还需要再次激活),输入命令行emcc -v来检测配置是否成功,配置成功即可进入文件中书写代码。

代码编写完成后进入cmd窗口,输入命令行emcc 文件名 ,编译器就会对该文件进行编译.

当我们查看文件夹时,会发现多出来两个文件,一个是wasm格式的文件,一个是js格式的文件,前者是二进制文件,可以wasm2wat中打开该文件,后者放在html当中引入即可发现文件顺利转换且生效.

调用一个在C中的自定义方法

1.在文件夹下创建streaming文件夹,创建streaming.c文件,编写c语言代码

c 复制代码
#include <emscripten.h>

EMSCRIPTEN_KEEPALIVE
int sumOfNInts(int n)
{
    // return n*(n+1)/2;
    return my_div(mul(n,add(n,1)),2);
}

2.打开对应代码文件的cmd窗口,然后输入emcc streaming.c -o streaming.js

3.输入命令之后的效果如图所示

4.在html页面中调用c语言函数

  1. 实例化wasm模块
  2. 创建全局变量存储exports
  3. 使用exports来调用C语言函数
html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  </head>
  <body>
    <p>你好,WebAssembly!</p>
    <input type="number" id="a">
    <button onclick="run_wasm()">trigger触发</button>
    <p id="res"></p>
  </body>
  <script>
    // 创建变量来存储exports,使得可以全局访问
    let exports 
    // 实例化wasm模块
    WebAssembly.instantiateStreaming(
      fetch("streaming.wasm"),{}
    ).then(result => exports = result.instance.exports);

    function run_wasm(){

      let a = document.querySelector('#a').value;
      // 使用exports调用c语言函数
      let sum = exports.sumOfNInts(a);

      document.querySelector("#res")
        .innerHTML += `${a} => ${sum}<br/>`;

    }
  </script>
</html>
内存模型

1.使用js来操作wasm内存

  1. 初始化内存(设置内存大小,以及内存最大扩容量)
  2. 创造视图
    1. 使用typearray, 使用new关键字构造Uint32Array,不同类型数据需要使用不同的typearray,如数字类型数据需要使用Uint32Array,字符串类型需要使用Uint8Array;
    2. typearray(buffer:any,byteOffset?:number,length?:number)
    3. buffer指的是内存本身,byteOffset是偏移量,length是所需内存长度
  3. 通过视图操作内存
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <p>你好,WebAssembly!</p>
  <input type="number" id="a">
  <button onclick="run_wasm()">trigger触发</button>
  <button onclick="getStr()">获取字符串</button>
  <p id="res"></p>
</body>
<script>
  let memeory = new WebAssembly.Memory({
    initial:256,
    maximum:512
  })
  // 创建变量来存储exports,使得可以全局访问
  let exports 
  WebAssembly.instantiateStreaming(
    fetch("memory.wasm"),{
      js:{
        mem:memeory
      }
    }
  ).then(result =>{ 
    exports = result.instance.exports;
    memory = result.instance.exports.memory;
  });
  
  function run_wasm(){
    let arr = new Uint32Array(memory.buffer);
    for(let i =0;i<10;i++){
      arr[i] = i*2;
    }

    let sum = exports.accumulate(0,10);
    
    document.querySelector("#res")
      .innerHTML += `${sum}<br>`;
  }

</script>
</html>

2.使用c语言来向内存中写入数据,然后js来调用c语言函数读取内存

c 复制代码
#include <emscripten.h>

int main()
{
    return 0;
}

EMSCRIPTEN_KEEPALIVE
const  char *getString()
{
    return "Hello,WebAssembly!"
}
javascript 复制代码
let memory = new WebAssembly.Memory({
  initial:256,
  maximum:512
})

let exports;
WebAssembly.instantiateStreaming(
  fetch("memory.wasm"),{
    js:{
      mem:memory
    }
  }
).then(result => {
  exports = result.instance.exports;
  memory = result.instance.exports.memory;
})

function getStr(){
  let ptr = exports.getString();
  let bytes = new Uint8Array(exports.buffer,ptr);
  let strlen = 0;
  while(bytes[strlen]){strlen++};

  let str = new TextDecoder("utf8").decode(
    bytes.slice(0,strlen)
  )
  console.log(str);
}
相关推荐
MediaTea1 小时前
人工智能通识课:机器学习之监督学习
人工智能·学习·机器学习
三品吉他手会点灯1 小时前
C语言学习笔记 - 27.C编程预备计算机专业知识 - 什么是字节
c语言·开发语言·笔记·学习
中屹指纹浏览器1 小时前
指纹浏览器硬件仿真技术解析:显卡、音频、外设指纹伪装原理
经验分享·笔记
yunhuibin2 小时前
videopipe学习之节点数据流转机制探索
学习
李少兄2 小时前
编程中的 e 表示法:科学计数法在代码里的指南
笔记·科学计数法·e
憧憬成为java架构高手的小白2 小时前
n8n学习(基于b站秋芝2046)
学习
星幻元宇VR3 小时前
VR大空间:沉浸式数字体验引领新时代科普与教育升级
科技·学习·安全·vr·虚拟现实
zhonghaoxincekj3 小时前
轴距可调式元器件双边无损成形钳
经验分享·科技·深度学习·学习·测试工具·创业创新·制造
ouliten3 小时前
[Triton笔记3]融合 Softmax (Fused Softmax)
笔记·triton