写点什么

WebAssembly 技术 _ 在 Web 端运行 C 与 C++ 程序 (ubuntu18.04)

作者:DS小龙哥
  • 2022 年 3 月 23 日
  • 本文字数:4047 字

    阅读完需:约 13 分钟

1. 前言

WebAssembly/wasm WebAssembly 或者 wasm 是一个可移植、体积小、加载快并且兼容 Web 的全新格式。


WebAssembly(缩写为 wasm)是一种使用非 JavaScript 代码,并使其在浏览器中运行的方法。这些代码可以是 C、C++ 或 Rust 等。它们会被编译进你的浏览器,在你的 CPU 上以接近原生的速度运行。这些代码的形式是二进制文件,你可以直接在 JavaScript 中将它们当作模块来用。


WebAssembly 不能替代 Javascript,相反,这两种技术是相辅相成的。通过 JavaScript API,你可以将 WebAssembly 模块加载到你的页面中。也就是说,你可以通过 WebAssembly 来充分利用编译代码的性能,同时保持 JavaScript 的灵活性。


官网介绍: https://www.wasm.com.cn/

2. ubuntu 18.04 安装编译器

进行下面步骤前,需要先安装 git,cmake 和 python 工具。


安装完毕后,确认 git,cmake 和 python 已经在你的环境变量里,可以使用再继续。


ubuntu 系统安装比较容易:


wbyq@wbyq:~/work_pc/WebAssembly/emsdk$ sudo apt  install cmakewbyq@wbyq:~/work_pc/WebAssembly/emsdk$ sudo apt  install pythonwbyq@wbyq:~/work_pc/WebAssembly/emsdk$ sudo apt  install git
复制代码


(1)创建工作目录,存放接下来下载的相关文件


wbyq@wbyq:~/work_pc$ mkdir WebAssemblywbyq@wbyq:~/work_pc$ cd WebAssembly/
复制代码


(2)从仓库克隆项目


wbyq@wbyq:~/work_pc/WebAssembly$ git clone https://github.com/emscripten-core/emsdk.git 正克隆到 'emsdk'...remote: Enumerating objects: 3138, done.remote: Total 3138 (delta 0), reused 0 (delta 0), pack-reused 3138接收对象中: 100% (3138/3138), 1.66 MiB | 174.00 KiB/s, 完成.处理 delta 中: 100% (2043/2043), 完成.wbyq@wbyq:~/work_pc/WebAssembly$ lsemsdkwbyq@wbyq:~/work_pc/WebAssembly$ cd emsdk/wbyq@wbyq:~/work_pc/WebAssembly/emsdk$ lsbazel            emscripten-releases-tags.json  emsdk_env.bat   emsdk_env.ps1        emsdk.ps1                 legacy-emscripten-tags.txt  README.mddocker           emsdk                          emsdk_env.csh   emsdk_env.sh         emsdk.py                  LICENSE                     scriptsemcmdprompt.bat  emsdk.bat                      emsdk_env.fish  emsdk_manifest.json  legacy-binaryen-tags.txt  llvm-tags-64bit.txt         test
复制代码


(3)安装最新的编译器


wbyq@wbyq:~/work_pc/WebAssembly/emsdk$ ./emsdk install latestResolving SDK alias 'latest' to '3.1.4'Resolving SDK version '3.1.4' to 'sdk-releases-upstream-39e60dda6945cfcd6487725bdb1361ae7975173f-64bit'Installing SDK 'sdk-releases-upstream-39e60dda6945cfcd6487725bdb1361ae7975173f-64bit'..Installing tool 'node-14.18.2-64bit'..Error: Downloading URL 'https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/node-v14.18.2-linux-x64.tar.xz': <urlopen error unknown url type: https>Warning: Possibly SSL/TLS issue. Update or install Python SSL root certificates (2048-bit or greater) supplied in Python folder or https://pypi.org/project/certifi/ and try again.error: installation failed!
复制代码


搭建环境过程中的会经历的正常流程。。。。。。


文件无法下载,那么接下来就手动下载文件。


(4)创建 zips 目录,这个目录存放接下来手动下载的软件压缩包,手动将所有需要的包都下载好了,再次运行 ./emsdk install latest命令即可自动解压安装。


wbyq@wbyq:~/work_pc/WebAssembly/emsdk$ mkdir zips
复制代码


(5)修改 emsdk.py 文件


emsdk.py 里存放的就是文件下载代码,需要把下载部分代码屏蔽掉,打印出下载的 url 地址,然后自己使用 wget 命令手动下载,下载之后将文件放到 zips 目录下。


wbyq@wbyq:~/work_pc/WebAssembly/emsdk$ gedit emsdk.py 
复制代码


修改后的文件:




(6)接下来陆续的下载文件


先执行./emsdk install latest命令,会报错并提示输出下载地址,得到下载地址使用 wget 手动下载,下载后将压缩包放到 zips 目录下,然后继续执行./emsdk install latest命令,又会有新的下载地址提示,然后一直持续到所有包都下载安装完毕, 也就是./emsdk install latest命令成功运行不再报错就完成了。


wbyq@wbyq:~/work_pc/WebAssembly/emsdk$ wget https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/node-v14.18.2-linux-x64.tar.xz--2022-02-17 15:25:06--  https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/node-v14.18.2-linux-x64.tar.xz正在解析主机 storage.googleapis.com (storage.googleapis.com)... 142.251.43.16, 172.217.163.48, 172.217.160.80, ...正在连接 storage.googleapis.com (storage.googleapis.com)|142.251.43.16|:443... 已连接。已发出 HTTP 请求,正在等待回应... 200 OK长度: 21848416 (21M) [application/x-tar]正在保存至: “node-v14.18.2-linux-x64.tar.xz”
node-v14.18.2-linux-x64.tar.xz 100%[=========================================================================>] 20.84M 9.16MB/s 用时 2.3s
2022-02-17 15:25:09 (9.16 MB/s) - 已保存 “node-v14.18.2-linux-x64.tar.xz” [21848416/21848416])
wbyq@wbyq:~/work_pc/WebAssembly/emsdk$ mv node-v14.18.2-linux-x64.tar.xz zips/wbyq@wbyq:~/work_pc/WebAssembly/emsdk$ ./emsdk install latestResolving SDK alias 'latest' to '3.1.4'Resolving SDK version '3.1.4' to 'sdk-releases-upstream-39e60dda6945cfcd6487725bdb1361ae7975173f-64bit'Installing SDK 'sdk-releases-upstream-39e60dda6945cfcd6487725bdb1361ae7975173f-64bit'..Skipped installing node-14.18.2-64bit, already installed.Installing tool 'releases-upstream-39e60dda6945cfcd6487725bdb1361ae7975173f-64bit'..--------------------------------------------------------
https://storage.googleapis.com/webassembly/emscripten-releases-builds/linux/39e60dda6945cfcd6487725bdb1361ae7975173f/wasm-binaries.tbz2--------------------------------------------------------
Unpacking '/home/wbyq/work_pc/WebAssembly/emsdk/zips/39e60dda6945cfcd6487725bdb1361ae7975173f-wasm-binaries.tbz2' to '/home/wbyq/work_pc/WebAssembly/emsdk/upstream'tar: /home/wbyq/work_pc/WebAssembly/emsdk/zips/39e60dda6945cfcd6487725bdb1361ae7975173f-wasm-binaries.tbz2:无法 open: 没有那个文件或目录tar: Error is not recoverable: exiting now['tar', '-xf', '/home/wbyq/work_pc/WebAssembly/emsdk/zips/39e60dda6945cfcd6487725bdb1361ae7975173f-wasm-binaries.tbz2', '--strip', '1'] failed with error code 2!error: installation failed!
复制代码


注意,有些包下载下来的名称与安装使用的名称对不上,导致安装失败,需要重新根据提示命名就能解决。



(7)激活 SDK


wbyq@wbyq:~/work_pc/WebAssembly/emsdk$ ./emsdk activate latest
复制代码



(8)生效环境变量


wbyq@wbyq:~/work_pc/WebAssembly/emsdk$ source emsdk_env.sh
复制代码


该命令只能在当前终端生效,可以将命令加到 etc/profile 里,重启系统全局生效。

3. 编写 C/C++代码测试

下面编写一个 C 语言代码,导出函数接口,给前端 JS 调用测试。


(1)编写简单的 C 代码,提供 1 个测试函数


int square(int x) {  return x * x;}
复制代码


(2)编译测试


emcc ./app.c -Os -s WASM=1 -s SIDE_MODULE=1 -o ./app.wasm
复制代码


(3)编写 js 文件调用测试。名称设置为:loader.js,因为下面 HTML 文件里引用的名称叫 loader.js,也可以改成别的。


function loadWebAssembly(filename, imports = {}) {  return fetch(filename)    .then(response => response.arrayBuffer())    .then(buffer => {      imports.env = imports.env || {}      Object.assign(imports.env, {        memoryBase: 0,        tableBase: 0,        __memory_base: 0,        __table_base: 0,        memory: new WebAssembly.Memory({ initial: 256, maximum: 256 }),        table: new WebAssembly.Table({ initial: 0, maximum: 0, element: 'anyfunc' })      })      return WebAssembly.instantiate(buffer, imports)    })    .then(result => result.instance )}
function loadJS (url, imports = {}) { return fetch(url) .then(response => response.text()) .then(code => new Function('imports', `return (${code})()`)) .then(factory => ({ exports: factory(imports) }))}
复制代码


(4)编写一个 HTML 文件。名称设置为: index.html


<!DOCTYPE html><html><head>  <meta charset="utf-8">  <title>Compile C to WebAssembly</title>  <meta name="apple-mobile-web-app-capable" content="yes" />  <meta name="apple-mobile-web-app-status-bar-style" content="black" />  <meta name="apple-touch-fullscreen" content="yes" />  <meta name="format-detection" content="telephone=no, email=no" />  <script src="./loader.js"></script></head>
<body> <h1>Compile C to WebAssembly</h1> <p>The test result can be found in console.</p>
<script> loadWebAssembly('./app.wasm') .then(instance => { const square = instance.exports.square
console.log('2^2 =', square(2)) console.log('3^2 =', square(3)) console.log('(2 + 5)^2 =', square(2 + 5)) }) </script></body></html>
复制代码


(5)启动 HTTP 服务器


python -m http.server
复制代码


(6)打开浏览器访问


按下 F12,查看控制台的输出。


http://127.0.0.1:8000/index.html
复制代码


发布于: 2022 年 03 月 23 日阅读数: 5
用户头像

DS小龙哥

关注

之所以觉得累,是因为说的比做的多。 2022.01.06 加入

熟悉C/C++、51单片机、STM32、Linux应用开发、Linux驱动开发、音视频开发、QT开发. 目前已经完成的项目涉及音视频、物联网、智能家居、工业控制领域

评论

发布
暂无评论
WebAssembly技术_在Web端运行C与C++程序(ubuntu18.04)_webassembly_DS小龙哥_InfoQ写作平台