背景
在 OpenHarmony 应用里复用已有的 C/C++ 算法库(加密、图像处理、物理模拟等),传统做法是写 NAPI 适配层。但 Flutter 生态下还有另一条路:把 C/C++ 编译成 WebAssembly,再通过 wasm_ffi 库在 Dart 侧加载调用。这样做的好处是代码复用度高,而且跨平台时不用反复调 NAPI 接口。
这篇文章记录我在鸿蒙设备上集成 wasm_ffi 的过程,主要包括:
- 基础原理和内存模型
- 初始化、加载模块、调用导出函数的代码
- 大数据量交互时的内存操作
- 鸿蒙特有的两个适配坑(指令审计和线性内存压缩)
- 一个简单的 UI 演示页面
1. 原理简述
wasm_ffi 底层靠 Dart FFI 与 WASM 运行时交互。它把 .wasm 文件解析成内存结构,然后你能用 Dart 函数签名去映射 WASM 里导出的 C 风格函数。调用时数据几乎零拷贝,因为 WASM 的线性内存可以直接共享给 Dart 侧。
流程大致是:
- 把
.wasm放进鸿蒙应用资产目录。 - 运行时加载字节流,创建 WASM 模块实例。
- 从实例里查找函数,得到 Dart 可调用的函数对象。
- 调用函数,必要时通过实例的
memory接口传递大量数据。
在鸿蒙上这样做有两个明显收益:
- 性能:避免 JSON 序列化/反序列化,大数据处理时吞吐量明显好一截。
- 安全:WASM 沙箱隔离敏感逻辑,比如加密算法,即使应用层内存被 dump,也难以逆向。
2. 在鸿蒙项目里接入
wasm_ffi 本身不算鸿蒙官方库,但依赖的 Dart FFI 鸿蒙是支持的。需要注意文件权限,把 .wasm 放在 rawfile 目录并在 module.json5 里确保可访问。
2.1 添加依赖
pubspec.yaml:
dependencies:
wasm_ffi: ^0.1.0
2.2 基础调用示例
加载一个简单的 add_ints 函数:
import 'package:wasm_ffi/wasm_ffi.dart';
import 'package:flutter/services.dart';
Future<void> initWasm() async {
// 读取 wasm 文件
final data = await rootBundle.load('assets/native_core.wasm');
final bytes = data.buffer.asUint8List();
// 编译并实例化
final module = await WasmModule.load(bytes);
final instance = module.instantiate();
// 查找导出函数
final adder = instance.lookupFunction('add_ints');
// adder 声明为 int Function(int, int)
print('结果: ${adder(10, 20)}');
}
2.3 处理线性内存
对图像处理这类场景,可以直接往 WASM 线性内存里写像素数据,调用后台算法再读回结果。
void processImage(WasmInstance instance, Uint8List pixels) {
final memory = instance.memory;
// 拷贝数据到 WASM 堆空间
memory.view.setRange(0, pixels.length, pixels);
// 调用滤镜函数,传入数据长度
instance.call('apply_heavy_filter', [pixels.length]);
// 算法内会原地修改内存
}


