likes
comments
collection
share

使用wasm-pack构建和发布Rust WebAssembly

作者站长头像
站长
· 阅读数 26

概述

WebAssembly(通常简称为Wasm)是一种新的代码格式,允许在Web浏览器中运行接近原生性能的应用程序。Rust是一种系统编程语言,以其安全性、并发性和性能而闻名。将Rust编译为WebAssembly并集成到Web应用程序中,可以充分利用这两种技术的优势。

安装wasm-pack

首先,你需要安装wasm-pack,这是一个Rust工具,用于构建和打包Rust WebAssembly项目。你可以从官方GitHub仓库获取安装指南。

创建Rust WebAssembly项目

使用cargo,Rust的包管理器和构建工具,来创建一个新的库项目:

cargo new --lib my_wasm_project
cd my_wasm_project

这里--lib参数告诉Cargo创建一个库而不是二进制项目,因为WebAssembly模块通常作为库被Web应用程序使用。

添加依赖

Cargo.toml文件中添加wasm-bindgen作为依赖项:

[dependencies]
wasm-bindgen = "0.2"

使用wasm-bindgen

wasm-bindgen是一个宏,它允许你将Rust代码暴露给JavaScript。你需要在Rust代码中使用这个宏来定义你想要在JavaScript中使用的函数和类型。

创建一个lib.rs文件,并使用wasm_bindgen宏:

extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn say_hello() -> String {
    "Hello from Rust!".to_string()
}

这里#[wasm_bindgen]宏将say_hello函数暴露给JavaScript。

构建项目

使用wasm-pack构建你的项目:

wasm-pack build --target web

这将编译你的Rust代码为WebAssembly,并生成一个包含JavaScript胶水代码的pkg目录。

将WebAssembly模块导入到JavaScript

在构建完成后,你可以在JavaScript中导入生成的模块。首先,确保你的HTML文件链接了生成的JavaScript文件:

<script type="module">
  import init, { say_hello } from './pkg/my_wasm_project.js';

  async function run() {
    await init(); // 初始化WebAssembly模块
    console.log(say_hello()); // 调用Rust函数
  }

  run();
</script>

这里使用了ES6模块语法来导入init函数和say_hello函数。init函数是必需的,它初始化WebAssembly模块。

扩展Rust和JavaScript的数据交互

基本数据类型交互

在Rust和JavaScript之间传递基本数据类型(如字符串、布尔值和数字)相对简单。以下是一些示例:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn get_greeting(name: &str) -> String {
    format!("Hello, {}!", name)
}

#[wasm_bindgen]
pub fn is_valid(num: u32) -> bool {
    num > 10
}

#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

在JavaScript中调用这些函数:

const greeting = get_greeting("Alice");
console.log(greeting); // 输出: Hello, Alice!

const isValid = is_valid(15);
console.log(isValid); // 输出: true

const sum = add(5, 10);
console.log(sum); // 输出: 15

数组和复杂对象

对于数组和对象,你可以定义相应的Rust结构体,并使用wasm_bindgen来序列化和反序列化:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
#[derive(Clone)]
pub struct Person {
    name: String,
    age: u32,
}

#[wasm_bindgen]
impl Person {
    #[wasm_bindgen(constructor)]
    pub fn new(name: String, age: u32) -> Person {
        Person { name, age }
    }

    #[wasm_bindgen(method)]
    pub fn get_info(&self) -> String {
        format!("{} is {} years old", self.name, self.age)
    }
}

在JavaScript中创建和使用:

const person = new Person("Bob", 30);
console.log(person.get_info()); // 输出: Bob is 30 years old

异步通信:Rust的Future与JavaScript的Promise

在Web开发中,异步操作非常常见。JavaScript使用Promise来处理异步操作,而Rust使用Futurewasm-bindgen提供了一种方式来桥接这两种异步模型。

Rust中的Future

首先,你需要一个可以返回Future的Rust函数:

use wasm_bindgen::prelude::*;
use js_sys::Promise;
use wasm_bindgen_futures::future_to_promise;

#[wasm_bindgen]
pub fn fetch_data() -> Promise {
    let future = async {
        // 模拟异步操作
        let data = "Some data".to_string();
        // 返回结果
        JsValue::from_str(&data)
    };

    future_to_promise(future)
}

这里使用了wasm-bindgen-futures库来将Rust的Future转换为JavaScript的Promise

JavaScript中的Promise

在JavaScript中,你可以像处理普通Promise一样处理这个异步函数:

fetch_data().then(data => {
    console.log(data); // 输出: Some data
});

总结

通过上述步骤,你可以将Rust代码编译为WebAssembly,并使用wasm-bindgen宏将其暴露给JavaScript。这为开发高性能的Web应用程序提供了一种新的方法,结合了Rust的安全性和WebAssembly的性能。

此外,通过wasm-bindgenwasm-bindgen-futures,你可以在Rust和JavaScript之间进行复杂的数据类型交互和异步通信,进一步扩展了WebAssembly在Web开发中的应用范围。

进一步阅读

通过这些资源,你可以更深入地了解如何使用Rust和WebAssembly开发Web应用程序,并有效地处理异步数据交互。

转载自:https://juejin.cn/post/7388056383642697782
评论
请登录