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);
}
相关推荐
for_ever_love__5 小时前
UI学习:UISearchController基础了解和应用
学习·ui·ios·objective-c
心中有国也有家5 小时前
GE图引擎深度解析——CANN的计算图优化与执行引擎
人工智能·pytorch·python·学习·numpy
東雪木6 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
GHL2842710906 小时前
换脸工作流学习
学习·ai
_李小白7 小时前
【android opencv学习笔记】Day 28: 滤波算法之中值滤波器
android·opencv·学习
Oll Correct7 小时前
实验二十九:TCP的运输连接管理
网络·笔记
飞翔中文网8 小时前
Java学习笔记之抽象类与接口(设计思想)
java·笔记·学习
智者知已应修善业9 小时前
【proteus设计文氏正弦波信号发生器】2023-5-9
驱动开发·经验分享·笔记·硬件架构·proteus·硬件工程
土星碎冰机9 小时前
xxljob学习(大白话版本)
学习·运维开发
吃好睡好便好9 小时前
说说免疫力的维护
学习·生活