前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Rust日报】2023-06-07 使用 C++ 编写通用库并在 Rust 中使用它 (WASI)

【Rust日报】2023-06-07 使用 C++ 编写通用库并在 Rust 中使用它 (WASI)

作者头像
MikeLoveRust
发布2023-09-26 17:18:28
1890
发布2023-09-26 17:18:28
举报

使用 C++ 编写通用库并在 Rust 中使用它 (WASI)

WebAssembly 简介

WebAssembly 是一种二进制指令格式,旨在成为一种低级虚拟机,可以在 Web 浏览器中以接近本机的速度运行代码。它不特定于网络,也可以在其他平台上运行。WebAssembly 代码可以从各种编程语言编译而来,例如 C、C++、Rust、C# 等。 Wasmer 是一个轻量级且快速的 WebAssembly 运行时,可以在各种平台上运行 WebAssembly 模块,包括 Windows、Linux 和 macOS。Wasmer 支持多种编程语言,包括 C、C++、Rust 等。

使用 C++ 创建 WebAssembly 库

首先,我们将使用 C++ 创建一个简单的“加法”函数,它将两个整数作为输入并返回它们的和。

代码语言:javascript
复制
// add.cpp 

extern  "C" { 
    int  add ( int a, int b)  { 
        return a + b; 
    } 
}

在这段代码中,我们将使用 Rust 中的 add 函数。使用外部“C”是为了使函数“add”不被编译器破坏。我们将不得不在我们的 Rust 代码中使用相同的名称。以下是将代码编译为 WebAssembly 的更新命令:

代码语言:javascript
复制
wasmc++ add.cpp -o add.wasm

完成执行后,您应该能够看到文件 add.wasm。我们会将这个 Web 程序集加载到我们的 Rust 项目中。

在 Rust 中使用它

让我们使用创建一个简单的 Rust 项目

代码语言:javascript
复制
cargo new wasmer-consume

在 Cargo.toml 中添加如下依赖

代码语言:javascript
复制
wasmer = “3.1.1” 
wasmer-wasi = “3.1.1”

替换main.rs中的以下代码

代码语言:javascript
复制
use wasmer::{Instance, Module, Store, Value, Function};
use wasmer_wasi::{WasiState, WasiEnv, generate_import_object_from_env, WasiFunctionEnv};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Read the WebAssembly module bytes
    let wasm_bytes = include_bytes!("/Users/shyamsundarb/Library/cppWrk/wasmerblog/wasmer-consume/add.wasm");
    
    // Create a new store to hold WebAssembly instances
    let mut store = Store::default();

    // Create a new WASI state for the WASI environment
    let wasi_state = WasiState::new("wasi_snapshot_preview1").build()?;
    
    // Create a new WASI environment using the WASI state
    let wasi_env = WasiEnv::new(wasi_state);

    // Compile the WebAssembly module from the provided bytes
    let module = Module::new(&store, wasm_bytes)?;

    // Create a new instance of the WASI functions using the store and WASI environment
    let wasi_func = WasiFunctionEnv::new(&mut store, wasi_env);

    // Generate the import object from the WASI functions and environment
    let mut import_object = generate_import_object_from_env(&mut store, &wasi_func.env, wasmer_wasi::WasiVersion::Latest);
    
    // Create a host function that exits the program
    let exit_func = Function::new_typed(&mut store, |i: i32| {
        std::process::exit(i);
    });

    // Add the missing `proc_exit` function to the import object
    import_object.define("wasi_snapshot_preview1", "proc_exit", exit_func);
    
    // Create a new instance of the WebAssembly module with the import object
    let instance = Instance::new(&mut store, &module, &import_object)?;

    // Get the `add` function from the instance exports
    let add: &Function = instance.exports.get_function("add")?;

    // Call the `add` function with two integer arguments
    let result = add.call(&mut store, &[Value::I32(2), Value::I32(3)])?;
    
    // Retrieve the result value from the function call
    let result_value: i32 = result[0].unwrap_i32();

    // Print the result
    println!("Result: {}", result_value);

    Ok(())
}

当您运行 cargo run 命令时,如果一切顺利,您应该会看到以下内容:

.

我们可以看到该函数在控制台应用程序中可用。现在让我们看看如何在浏览器中使用它。

结论

尽管这个例子很简单,但从概念上讲,它为“一次编写,到处运行”开辟了新的含义。Webassembly 作为一项技术仍处于初期阶段。它帮助我们弥合编程语言和平台之间的鸿沟。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-06-08 16:04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Rust语言学习交流 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用 C++ 编写通用库并在 Rust 中使用它 (WASI)
    • WebAssembly 简介
      • 使用 C++ 创建 WebAssembly 库
        • 在 Rust 中使用它
          • 结论
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档