Flutter WebAssembly交互插件wasm_interop的使用

发布于 1周前 作者 songsunli 来自 Flutter

Flutter WebAssembly交互插件wasm_interop的使用

WebAssembly JS API Bindings for Dart

WebAssembly JavaScript接口为Dart提供了与WebAssembly交互的能力。wasm_interop包是Dart对WebAssembly JavaScript API的绑定,它允许开发者在Dart中直接操作和调用WebAssembly模块的功能。本文将详细介绍如何使用wasm_interop包来加载和执行WebAssembly模块,并提供一个完整的示例。

Upstream Specification

Overview

此包提供的Dart绑定适用于独立的WebAssembly模块,即不需要专门的JavaScript胶水代码的模块。对于需要胶水代码的情况,Dart应用程序应通过dart:jspackage:js来处理。独立的WebAssembly模块可以由以下工具创建:

要在非JS环境中使用WebAssembly,可以参考wasm包。

Running tests

测试可以在所有可用平台上(Chrome、Firefox、Safari 和 node)以发布模式运行:

$ dart test

或者在Chrome上以调试模式(DDC)运行:

$ dart run build_runner test -- -p chrome

使用wasm_interop包的示例

下面是一个完整的示例,展示了如何使用wasm_interop包来加载和执行WebAssembly模块。这个例子包含了两个功能:一个是将浮点数重新解释为整数,另一个是在内存中填充随机字节并计算其中1的数量。

示例代码

main.dart

import 'dart:math';
import 'dart:typed_data';
import 'package:wasm_interop/wasm_interop.dart';

Future<void> main() async {
  await reinterpret();
  await count();
}

/// 将float64重新解释为i64
Future<void> reinterpret() async {
  /// WebAssembly 模块定义
  final moduleBytes = Uint8List.fromList(
      '\x00\x61\x73\x6D\x01\x00\x00\x00\x01\x06\x01\x60\x01\x7C\x01\x7E\x03\x02'
              '\x01\x00\x07\x13\x01\x0F\x72\x65\x69\x6E\x74\x65\x72\x70\x72\x65'
              '\x74\x5F\x69\x36\x34\x00\x00\x0A\x07\x01\x05\x00\x20\x00\xBD\x0B'
          .codeUnits);

  // 创建WebAssembly实例
  final instance = await Instance.fromBytesAsync(moduleBytes);

  // 获取导出的函数
  final reinterpretFunction =
      instance.functions['reinterpret_i64']! as Object Function(double v);
  final d = Random().nextDouble();
  final reinterpreted = JsBigInt.toBigInt(reinterpretFunction(d));

  print('$d -> $reinterpreted');
}

/// 计算内存中1的数量
Future<void> count() async {
  /// WebAssembly 模块定义
  final moduleBytes = Uint8List.fromList(
      '\x00\x61\x73\x6D\x01\x00\x00\x00\x01\x05\x01\x60\x00\x01\x7F\x03\x02\x01'
              '\x00\x05\x04\x01\x01\x01\x01\x07\x12\x02\x06\x6D\x65\x6D\x6F\x72'
              '\x79\x02\x00\x05\x63\x6F\x75\x6E\x74\x00\x00\x0A\x2C\x01\x2A\x02'
              '\x01\x7F\x01\x7E\x03\x40\x20\x00\x41\x80\x80\x04\x48\x04\x40\x20'
              '\x01\x20\x00\x29\x03\x00\x7B\x7C\x21\x01\x20\x00\x41\x08\x6A\x21'
              '\x00\x0C\x01\x0B\x0B\x20\x01\xA7\x0B'
          .codeUnits);

  // 创建WebAssembly实例
  final instance = await Instance.fromBytesAsync(moduleBytes);

  // 获取导出的内存对象并填充随机字节
  final memoryView = instance.memories['memory']!.buffer.asUint8List();
  final r = Random();
  for (var i = 0; i < memoryView.length; i++) {
    memoryView[i] = r.nextInt(256);
  }

  // 获取导出的函数并计算1的数量
  final totalCountFunction = instance.functions['count']! as int Function();

  print(totalCountFunction());
}

解释

  1. reinterpret 函数:

    • 定义了一个简单的WebAssembly模块,该模块包含一个函数reinterpret_i64,用于将输入的double值重新解释为int64
    • 使用Instance.fromBytesAsync方法从二进制数据创建WebAssembly实例。
    • 调用reinterpret_i64函数并将结果转换为JsBigInt,然后打印出来。
  2. count 函数:

    • 定义了另一个WebAssembly模块,该模块包含一个内存对象和一个函数count,用于计算内存中1的数量。
    • 同样使用Instance.fromBytesAsync方法创建实例。
    • 填充内存对象中的随机字节。
    • 调用count函数并打印结果。

总结

通过wasm_interop包,开发者可以在Dart中轻松地加载和执行WebAssembly模块,从而实现高性能的计算任务。上述示例展示了如何定义WebAssembly模块并在Dart中与其进行交互。希望这个例子能帮助你更好地理解和使用wasm_interop包。


更多关于Flutter WebAssembly交互插件wasm_interop的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter WebAssembly交互插件wasm_interop的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter应用中,与WebAssembly(Wasm)进行交互可以通过wasm_interop插件来实现。wasm_interop允许你在Flutter的Dart代码中加载并调用WebAssembly模块。以下是一个简单的示例,展示了如何在Flutter应用中使用wasm_interop与Wasm模块进行交互。

前提条件

  1. 确保你的Flutter环境已经设置好,并且你有一个Flutter项目。
  2. 你需要一个WebAssembly模块(.wasm文件)。为了简单起见,假设你有一个简单的Wasm模块,它执行一些基本的数学运算。

步骤 1: 创建Wasm模块

首先,你需要一个Wasm模块。这里我们使用一个简单的Rust程序来编译成Wasm模块,但你也可以使用其他语言(如C/C++)来编写Wasm模块。

Rust代码(simple_math.rs):

#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
    a + b
}

编译这个Rust代码为Wasm模块:

rustup target add wasm32-unknown-unknown
cargo build --target wasm32-unknown-unknown --release
wasm-bindgen --target web --out-dir ./out target/wasm32-unknown-unknown/release/simple_math.wasm

这将在./out目录下生成一个simple_math.jssimple_math_bg.wasm文件。我们将使用simple_math_bg.wasm文件。

步骤 2: 添加Wasm文件到Flutter项目

将生成的simple_math_bg.wasm文件复制到你的Flutter项目的assets文件夹中(如果没有,请创建一个)。然后在pubspec.yaml文件中添加Wasm文件作为资产:

flutter:
  assets:
    - assets/simple_math_bg.wasm

步骤 3: 使用wasm_interop插件

在你的pubspec.yaml文件中添加wasm_interop依赖:

dependencies:
  flutter:
    sdk: flutter
  wasm_interop: ^0.1.0  # 请检查最新版本号

步骤 4: 编写Dart代码加载并调用Wasm模块

在你的Flutter项目中,创建一个Dart文件(例如wasm_service.dart)来加载和调用Wasm模块:

import 'dart:typed_data';
import 'dart:web_assembly' as wasm;
import 'package:flutter/services/asset_bundle.dart';
import 'package:wasm_interop/wasm_interop.dart';

class WasmService {
  late wasm.Module module;
  late wasm.Function addFunction;

  WasmService() async {
    // Load the .wasm file from assets
    final ByteData wasmData = await rootBundle.load('assets/simple_math_bg.wasm');
    Uint8List wasmBytes = wasmData.buffer.asUint8List();

    // Instantiate the Wasm module
    module = await wasm.instantiate(wasmBytes, {});

    // Get the exported function 'add'
    addFunction = module.exports['add'] as wasm.Function;
  }

  int add(int a, int b) {
    // Call the 'add' function
    return addFunction.call(a, b) as int;
  }
}

步骤 5: 在你的Flutter组件中使用WasmService

在你的Flutter组件中(例如main.dart),使用WasmService

import 'package:flutter/material.dart';
import 'wasm_service.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Wasm Interop Example'),
        ),
        body: Center(
          child: FutureBuilder<int>(
            future: _calculateSum(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                if (snapshot.hasError) {
                  return Text('Error: ${snapshot.error}');
                } else {
                  return Text('Sum: ${snapshot.data}');
                }
              } else {
                return CircularProgressIndicator();
              }
            },
          ),
        ),
      ),
    );
  }

  Future<int> _calculateSum() async {
    WasmService wasmService = await WasmService();
    return wasmService.add(5, 10);
  }
}

总结

这个示例展示了如何在Flutter应用中加载和使用WebAssembly模块。通过wasm_interop插件,你可以轻松地与Wasm模块进行交互,从而利用Wasm的性能优势来增强你的Flutter应用。请确保你的Wasm模块和Dart代码之间的接口是匹配的,以避免运行时错误。

回到顶部