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.jshello.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 了