发表于: 2019-12-22 13:34:13

1 1246


今日完成:

WebAssembly的使用

介绍

WebAssembly(缩写为Wasm)是基于堆栈的虚拟机的二进制指令格式。Wasm被设计为可移植目标,用于编译高级语言(如C / C ++ / Rust),从而可以在Web上为客户端和服务器应用程序进行部署。

安装环境

在windows环境下构建WebAssembly的工具链Emscripten

在开始构建安装之前,你需要确保你本地已经安装好了以下的工具:

  • Git
  • CMake
  • Python 2.7.x

一切准备就绪后,就可以通过Emscripten SDK来构建Emscripten了。步骤如下:

  1. git clone https://github.com/emscripten-core/emsdk.git
  2. cd emsdk
  3. git pull
  4. ./emsdk install latest
  5. ./emsdk activate latest
  6. emsdk_env.bat

其中最关键的是第四步,也是比较耗时的一步,耐心等待吧。
安装好了之后,需要注意的是每次重新打开命令行控制台后,都需要进行第5、6步骤,
才能正常使用Emscripten工具来编译。可以通过命令emcc -v来检测。结果如下则表示安装成功可以正常使用:

PS D:\webAssemblyDemo\emsdk> emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 1.39.4
clang version 10.0.0 (Cswircachegitchromium.googlesource.com-external-github.com-llvm-llvm--project b5f295ffcec2fa7402e39eb1262acbd55a7d39f5)
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: D:/webAssemblyDemo/emsdk/upstream/bin
shared:INFO: (Emscripten: Running sanity checks)

可以看到emcc版本为1.39.4 ,一般按照上面步骤正常操作的话版本都没有问题,但如果你的版本在1.37或更低,那你就需要注意了:

emcc 在 1.37 以上版本才支持直接生成 wasm 文件。

开始一个简单的Demo

参考官方给出的demo来进行WebAssembly的初试:编写一个简单的C程序,使用emcc命令将其进行编译,最后在浏览器中运行。

• 在使用emcc命令时,要带着 -s WASM=1参数(不然,默认会编译成asm.js)
• 如果我们想让Emscripten生成一个我们所写程序的HTML页面,并带有wasm和JavaScript文件,我们需要给输出的文件名加.html后缀名。
• 最后,当我们运行程序的时候,我们不能直接在浏览器中打开HTML文件,因为跨域请求是不支持file协议的,我们需要将我们的文件输出在http协议上。

demo步骤如下:

  1. 编写C程序文件jnshu.c如下:

      #include<stdio.h>
      int main(int argc,char ** argv){
      printf("www.jnshu.com");
      }
  2. 使用命令emcc jnshu.c -s WASM=1 -o jnshu.html编译文件
    编译后会生成 jnshu.html、 jnshu.wasm、 jnshu.js三个文件

  1. 使用emrum命令来创建一个http协议的web server来展示编译后的文件
    emrun --no_browser --port 8080 .\jnshu.html

  2. 通过浏览器来访问

可以看到C程序打印的官网地址已经成功的在控制台上展示。

通过javascript来调用wasm文件

重新写一个C程序:

#include<stdio.h>
int square(int x){
    return x * x;
}

int add (int x, int y){
    return x + x;
}

这次的程序中没有main函数,只有两个方法。接下来使用emcc命令将其编译为wasm文件,并在js中调用它。

使用下面的命令直接将c编译为wasm文件:
emcc .\last.c -Os -s WASM=1 -s SIDE_MODULE=1 -o last.wasm


以十六进制编码的方式打开查看这个二进制文件:


它的开头几位为 20 61 73 6D,这个是判断一个文件是否符合wasm格式的标准。
它对应的ASCII码为: asm
之前说了emcc 在 1.37 以上版本才支持直接生成 wasm 文件。低版本通过命令貌似也可以生成一个后缀为.wasm的文件,编译过程不会报错。但在浏览器中调用wasm文件时就会报出wasm文件首部编码不匹配的问题。

有了wasm文件后,就可以在js中调用它了。
下面给出加载wasm模块的方法,这也是官方目前最为推荐的一种方式。
使用fetchAndInstantiate方法来获取WebAssembly模块,并将其实例化:

function fetchAndInstantiate(url, importObject={}) {
  return fetch(url).then(response =>
    response.arrayBuffer()
  ).then(bytes =>
    WebAssembly.instantiate(bytes, importObject)
  ).then(results =>
    results.instance
  );
}

js得到wasm实例后,就可以使用webAssembly.Instance.exports导出的方法了。

fetchAndInstantiate('math.wasm').then(function(instance) {
 //调用导出的函数
 var add = instance.exports.add
 var square = instance.exports.square
 console.log('1+1=',add(1,1))
 console.log('2*2=',square(2))
})

math.wasm需要与math.js在同一路径下。
最后将这段js代码加入math.html中,并通过htttp来访问:

如果你的浏览器是Firefox 54+的话,
其Developer Tool Debugger Panel模式可以将网页中包含的任何 wasm 代码转换为文本格式(wat),如下:

(export "add" $func1),(export "square" $func1)可以看到C程序中的两个方法被导出为add,square。这个很关键。看了很多教程,大家在使用如上方法调用wasm模块时,默认给方法名前加_,
如:var add = instance.exports._add。在低版本好像是这样的,导致我在升级版本后,调用模块总是提示没有此方法。查看了wasm的文本后才明白,新版直接调用方法名就可以了。

文章中所有的代码已整理放入github仓库:
https://github.com/zln312/webassembly_demo.git

参考文档:
https://webassembly.org/getting-started/developers-guide/
https://emscripten.org/docs/getting_started/downloads.html


明日计划:

继续js任务

学习微信小程序

收获:

发现了一款比较好用的笔记记录软件Joplin

简单了解了下markdown的使用,排版非常方便

遇到的问题:

最近总是熬夜,效率太低了。

以后不能再这样了,管理好时间。




返回列表 返回列表
评论

    分享到