当前位置: 首页 > news >正文

wasm 编译使用示例

WebAssembly 是一种新的编码方式,可以在现代的 Web 浏览器中运行——它是一种低级的类汇编语言,具有紧凑的二进制格式,可以接近原生的性能运行,并为诸如 C/C++、C# 和 Rust 等语言提供编译目标,以便它们可以在 Web 上运行。它也被设计为可以与 JavaScript 共存,允许两者一起工作。

以下示例,将展示如何使用 emscripten 编译 C++ 代码为 wasm 模块,并在 web 页面中调用。

一 安装 Emscripten

官方文档:https://emscripten.org/docs/getting_started/downloads.html#installation-instructions-using-the-emsdk-recommended

以下是详细安装步骤。

  1. 克隆 emsdk 仓库:
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
  1. 安装 SDK:
./emsdk.bat install latest
./emsdk.bat activate latest
  1. 配置环境变量:
source emsdk_env.sh
# windows
./emsdk_env.bat

在环境变量中定义 EMSDK、EMSDK_EMCC、EMSDK_NODE、EMSDK_PYTHON,并将其加入到环境变量中。

  1. 验证安装:
emcc --version

二 编译 wasm

1 C++ 代码示例

假如我们有一个 C++ 编写的数学库,需要暴露其中的 add 方法给 JavaScript 使用。其目录结构如下:

math/
├── math.h
├── math.cpp

头文件 math.h 和 源文件 math.cpp 内容如下:

// math.h
#ifndef MATH_H
#define MATH_Hint add(int a, int b);#endif
// math.cpp
int add(int a, int b) {return a + b;
}

2 编写绑定文件

math 目录同级,新建一个 bind 目录,用于存放绑定文件,然后在其中创建 math_bind.cpp,内容如下:

#include <emscripten/bind.h>
#include "math.h"using namespace emscripten;EMSCRIPTEN_BINDINGS(math_module) {function("add", &add);
}

在绑定文件中,我们使用 function 函数将 C++ 函数 add 暴露给 JavaScript 使用。

3 编译命令

bind 目录下执行以下命令:

em++ ../math/math.cpp ./math_bind.cpp -o ./build/math.js -s WASM=1 -s NO_EXIT_RUNTIME=1 --bind

上述命令中:

  • em++:emscripten 编译命令。
  • ../math/math.cpp:C++ 源文件路径。
  • ./math_bind.cpp:绑定文件路径。
  • -o ./build/math.js:输出文件路径。
  • -s WASM=1:生成 wasm 文件。
  • -s NO_EXIT_RUNTIME=1:防止退出 runtime。
  • --bind:生成绑定文件。

执行命令后,会在 bind 目录下的 build 目录中生成 math.jsmath.wasm 文件。

还有一些其他参数,可以将导出的 js 文件模块化,使之成为一个 es 模块,相关编译指令:

  • -s MODULARIZE=1:使生成的代码可以作为模块使用。
  • -s EXPORT_NAME='createMathWasmModule':指定模块的名称。

至此,C++ 代码已经编译导出 wasm 就完成了,在需要使用的地方引入 math.jsmath.wasm 文件即可。接下来我们编写 HTML 页面调用 wasm 模块。

三 测试使用 wasm

math 目录同级,新建一个 web 目录,用于存放网站相关文件。将 math.jsmath.wasm 文件拷贝到 web 目录中。在 web 目录下创建 index.html,内容如下:

<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><title>wasm 测试</title>
</head>
<body><h2>WASM 加法测试</h2><div><input type="number" id="num1" value="0"> +<input type="number" id="num2" value="0"> =<span id="result"></span></div><button onclick="calculate()">计算</button><script src="math.js"></script><script>// 等待WASM模块加载完成Module.onRuntimeInitialized = function () {console.log('WASM 模块已加载');}function calculate() {if (!Module) {console.error('WASM 未加载');return;}const num1 = parseInt(document.getElementById('num1').value);const num2 = parseInt(document.getElementById('num2').value);// 调用WASM中的add函数const sum = Module.add(num1, num2);document.getElementById('result').textContent = sum;}</script>
</body>
</html>

最终项目结构如下:

project/
├── bind/
│   ├── math_bind.cpp
│   └── build/
│       ├── math.js
│       └── math.wasm
├── math/
│   ├── math.h
│   └── math.cpp
├── web/
│   ├── index.html
│   └── math.js
│   └── math.wasm

若使用的模块好的,则可以通过 createMathWasmModule 函数获取 wasm 模块,然后调用其中的方法。

import createMathWasmModule from './math.js';const wasmModule = await createMathWasmModule();
console.log(wasmModule.add(1, 2));

http://www.mrgr.cn/news/62407.html

相关文章:

  • Swarm-LIO: Decentralized Swarm LiDAR-inertial Odometry论文翻译
  • 社区交流系统设计与实现
  • 相关矩阵图——Python实现
  • DDRPHY数字IC后端设计实现系列专题之后端设计导入,IO Ring设计
  • 江协科技STM32学习- P24 DMA数据转运DMA+AD多通道
  • day01-MybatisPlus
  • 使用 Elastic、OpenLLMetry 和 OpenTelemetry 跟踪 LangChain 应用程序
  • nacos No DataSource set
  • 学习伊圣雨老师的 epoll 编程:select是水平触发模式,回声客户端代码,epoll 服务器端,验证默认的水平触发模式,采用边缘触发模式
  • 5G基础知识
  • 真题与解析 202209一级 青少年软件编程(Python)考级
  • 设备管理系统中的故障率监控与维修周期优化
  • 浅析HTTP协议
  • 静态数据加密:确保数据在存储中的安全性
  • Postman断言与依赖接口测试详解
  • 数据治理,数据提取,大数据中心建设,大数据治理总体解决方案书(word,ppt原件)
  • 人工智能算法之A*搜索算法
  • 【Docker知识】Docker进阶-容器镜像深度解读
  • AIGC学习笔记(4)——AI大模型开发工程师
  • 高效集成:SQLServer对接MySQL的实战案例
  • NR 5G 系统信息深度解析
  • 使用python提取日志里面的role_id、vip字段的值,(vip字段可能为空或者缺失,此时需要给默认值0):
  • 个人在ssm框架整合时犯的错误
  • 只尊重不教育,只筛选不改变
  • Threejs渲染3D字体介绍
  • gradio RuntimeError: async generator raised StopAsyncIteration