Skip to content

Hello WebAssembly ​

在线预览 ​

查看 wasm hello world

任务描述 ​

使用 c++写一个 sayHello 方法,并且编译成 Web Assembly,然后在前端调用控制台输出 hello world。

电脑环境安装 (Mac m2 为例) ​

首先需要有 Emscripten 安装在你的系统上。

Emscripten 是一个能将 C++代码编译为 WebAssembly 的工具。

  1. 下载 SDK

打开 Emscripten 的官方下载页面并按照页面上的指南进行操作。

官网地址 https://emscripten.org/docs/getting_started/downloads.html#platform-notes-installation-instructions-sdk

bash
# 克隆项目到本地
git clone https://github.com/emscripten-core/emsdk.git
  1. 配置 SDK

下载完成后,你需要按照提供的说明配置 SDK。

TIP

这里需要 Python3 环境,Mac 电脑默认就有 python3(遇到错误再解决就好了)

bash

# 导航到emsdk目录
cd emsdk

# 安装最新的SDK工具
./emsdk install latest

# 激活最新的SDK工具
./emsdk activate latest

# 配置环境变量
source ./emsdk_env.sh

日志如下:

bash
shaohai.li@192 emsdk % ./emsdk install latest
Resolving SDK alias 'latest' to '3.1.46'
Resolving SDK version '3.1.46' to 'sdk-releases-21644188d5c473e92f1d7df2f9f60c758a78a486-64bit'
Installing SDK 'sdk-releases-21644188d5c473e92f1d7df2f9f60c758a78a486-64bit'..
Skipped installing node-16.20.0-64bit, already installed.
Skipped installing python-3.9.2-64bit, already installed.
Skipped installing releases-21644188d5c473e92f1d7df2f9f60c758a78a486-64bit, already installed.
All SDK components already installed: 'sdk-releases-21644188d5c473e92f1d7df2f9f60c758a78a486-64bit'.
shaohai.li@192 emsdk % ./emsdk activate latest
Resolving SDK alias 'latest' to '3.1.46'
Resolving SDK version '3.1.46' to 'sdk-releases-21644188d5c473e92f1d7df2f9f60c758a78a486-64bit'
Setting the following tools as active:
   node-16.20.0-64bit
   python-3.9.2-64bit
   releases-21644188d5c473e92f1d7df2f9f60c758a78a486-64bit

Next steps:
- To conveniently access emsdk tools from the command line,
  consider adding the following directories to your PATH:
    /Users/shaohai.li/project/emsdk
    /Users/shaohai.li/project/emsdk/upstream/emscripten
- This can be done for the current shell by running:
    source "/Users/shaohai.li/project/emsdk/emsdk_env.sh"
- Configure emsdk in your shell startup scripts by running:
    echo 'source "/Users/shaohai.li/project/emsdk/emsdk_env.sh"' >> $HOME/.zprofile
shaohai.li@192 emsdk %
shaohai.li@192 emsdk % source ./emsdk_env.sh
Setting up EMSDK environment (suppress these messages with EMSDK_QUIET=1)
Setting environment variables:
PATH = /Users/shaohai.li/project/emsdk:/Users/shaohai.li/project/emsdk/upstream/emscripten:/Users/shaohai.li/project/ffmpeg:/Library/Frameworks/Python.framework/Versions/2.7/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Library/Apple/usr/bin:/Applications/Visual Studio Code.app/Contents/Resources/app/bin:/Users/shaohai.li/project/phantomjs-2.1.1-macosx/bin
shaohai.li@192 emsdk %
  1. 测试安装

在完成上述步骤后,可以运行以下命令来测试 Emscripten 是否已成功安装:

bash
emcc -v

如果 Emscripten 已成功安装,这个命令会显示 Emscripten 的版本信息。

正确会输出下面的内容:

bash
shaohai.li@192 emsdk % emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.46 (19607820c447a13fd8d0b7680c56148427d6e1b8)
clang version 18.0.0 (https://github.com/llvm/llvm-project 75501f53624de92aafce2f1da698b249a7293dc7)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /Users/shaohai.li/project/emsdk/upstream/bin
shaohai.li@192 emsdk %

编写 hello.cpp 文件 ​

这段代码导出了一个名为 sayHello 的函数,该函数返回一个字符串“Hello, World!”。

cpp
// 引入emscripten/bind.h,这是使用embind时需要的头文件
#include <emscripten/bind.h>

// 使用emscripten命名空间,以简化代码
using namespace emscripten;

// 定义一个名为sayHello的C++函数,它返回一个字符串"Hello, World!"
std::string sayHello() {
    return "Hello, World!";
}

// 使用EMSCRIPTEN_BINDINGS宏来创建一个模块。这个模块会将C++的函数、类或变量绑定到JavaScript中。
EMSCRIPTEN_BINDINGS(my_module) {
    // 使用function函数将sayHello函数绑定到模块中。在JavaScript中,我们可以通过Module.sayHello()来调用这个C++函数。
    function("sayHello", &sayHello);
}

接下来,你可以使用 Emscripten 将 C++文件编译成 WebAssembly 文件。在终端中,进入 C++文件的目录,并执行以下命令:

bash
emcc --bind -o hello.js hello.cpp

运行此命令后,你将在同一目录下获得两个新文件:hello.js和hello.wasm。

前端代码 ​

最后,创建一个 HTML 文件来运行 WebAssembly 模块。

创建一个名为 index.html 的文件,内容如下:

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Hello WebAssembly</title>
  </head>
  <body>
    <script src="hello.js"></script>
    <!-- 引入通过Emscripten生成的JavaScript文件 -->
    <script>
      // 当WebAssembly模块准备完毕时执行此函数
      Module.onRuntimeInitialized = function () {
        // 调用在C++代码中定义的sayHello函数,并在控制台打印返回的字符串
        console.log(Module.sayHello()); // 应该在控制台输出: "Hello, World!"
      };
    </script>
  </body>
</html>

这里 Module.onRuntimeInitialized 确保在 WebAssembly 模块准备好之后再调用 sayHello 函数。

本地跑起来 ​

  1. 使用 VSCode 安装 live server 插件

  2. 点击一下 index.html

  3. 使用 Live Server 托管 index.html 启动项目

在你的 VSCode 右下角会有一个 Go Live 按钮,点击它就可以托管 index.html 了