使用Emscripten编译WASM供NodeJS调用

木头的喵喵拖孩

配置 emscripten

找到一个空文件夹,运行下面的命令安装 emscripten

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Get the emsdk repo
git clone https://github.com/emscripten-core/emsdk.git

# Enter that directory
cd emsdk

# Fetch the latest version of the emsdk (not needed the first time you clone)
git pull

# Download and install the latest SDK tools.
./emsdk install latest

# Make the "latest" SDK "active" for the current user. (writes .emscripten file)
./emsdk activate latest

# Activate PATH and other environment variables in the current terminal
source ./emsdk_env.sh

# On Windows, run emsdk.bat instead of ./emsdk, and emsdk_env.bat instead of source ./emsdk_env.sh.

安装完成后需要把 emscripten 安装 根目录 和 根目录下的 upstream/emscripten 添加到环境变量,方便全局调用

Node.js 调用 WASM

编写 c++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <emscripten.h>

#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C
#endif

EXTERN_C EMSCRIPTEN_KEEPALIVE void sayHi()
{
printf("Hi!\n");
}

EXTERN_C EMSCRIPTEN_KEEPALIVE double add(double num1, double num2)
{
return num1 + num2;
}

如果源码中引入头文件语法报错,需要在 .vscode 中修改 c_cpp_properties.json 文件内容如下
加上”D:\Emscripten\emsdk\upstream\emscripten\system\include\**”
*!!注意!!*
**这里的 *c_cpp_properties.json* 是基于 MinGW 设置的语法检测,如果没有安装 MinGW,可以无视语法检测,后面一样可以编译成功**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**",
"D:\\Emscripten\\emsdk\\upstream\\emscripten\\system\\include\\**"
],
"defines": ["_DEBUG", "UNICODE", "_UNICODE"],
"compilerPath": "D:\\MinGW\\mingw64\\bin\\gcc.exe",
"cStandard": "c17",
"cppStandard": "gnu++14",
"intelliSenseMode": "windows-gcc-x64",
"configurationProvider": "ms-vscode.makefile-tools"
}
],
"version": 4
}

编译 c++

!!注意!!
emscripten 后台会使用 clang++ 来编译 c++程序,如果源码里面包含了 MinGW 提供的头文件,将会有兼容性问题,导致编译无法通过

1
2
emsdk_env && emcc .\src\main.cpp -o .\wasm\wasm_api.js -s WASM=1
# 如果在C++函数没有标识 EMSCRIPTEN_KEEPALIVE ,则编译需要加上参数 -s EXPORTED_FUNCTIONS="['_sayHi','_add']"

调用 c++

1
2
3
4
5
6
const wasm_api = require("../wasm/wasm_api.js");

wasm_api.onRuntimeInitialized = () => {
wasm_api._sayHi();
console.log(wasm_api._add(0.1, 0.2));
};

参考

Emscripten 官网
阮一峰 asm.js 和 Emscripten 入门教程
VSCode + WebAssembly 简易工程化配置
Node.js 使用 WebAssembly
解决“……called before runtime initialization”问题
EMSCRIPTEN_KEEPALIVE 的作用

  • 标题: 使用Emscripten编译WASM供NodeJS调用
  • 作者: 木头的喵喵拖孩
  • 创建于: 2023-11-03 09:17:28
  • 更新于: 2024-05-21 10:56:15
  • 链接: https://blog.xx-xx.top/2023/11/03/使用Emscripten编译WASM供NodeJS调用/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
此页目录
使用Emscripten编译WASM供NodeJS调用