Rust WASM运行时wasmtime的C API宏库wasmtime-c-api-macros使用指南:实现高效WebAssembly接口绑定

Rust WASM运行时wasmtime的C API宏库wasmtime-c-api-macros使用指南:实现高效WebAssembly接口绑定

安装

在项目目录中运行以下Cargo命令:

cargo add wasmtime-c-api-macros

或者在Cargo.toml中添加以下行:

wasmtime-c-api-macros = "34.0.2"

使用示例

下面是一个完整的示例,展示如何使用wasmtime-c-api-macros来绑定WebAssembly函数:

use wasmtime_c_api_macros::wasmtime_c_api;

// 定义一个Rust函数,将被暴露给WebAssembly
#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
    a + b
}

// 使用wasmtime_c_api宏生成C API绑定
wasmtime_c_api! {
    // 定义模块名
    module "math" {
        // 暴露add函数给WebAssembly
        export "add" fn add(a: i32, b: i32) -> i32;
    }
}

fn main() {
    // 初始化wasmtime引擎
    let engine = wasmtime::Engine::default();
    let mut store = wasmtime::Store::new(&engine, ());
    
    // 使用生成的绑定创建模块
    let module = wasmtime::Module::new(&engine, wasmtime_c_api::math::MODULE).unwrap();
    
    // 实例化模块
    let instance = wasmtime::Instance::new(&mut store, &module, &[]).unwrap();
    
    // 获取add函数并调用
    let add = instance.get_typed_func::<(i32, i32), i32>(&mut store, "add").unwrap();
    let result = add.call(&mut store, (2, 3)).unwrap();
    
    println!("2 + 3 = {}", result); // 输出: 2 + 3 = 5
}

高级用法

wasmtime-c-api-macros还支持更复杂的绑定场景:

use wasmtime_c_api_macros::wasmtime_c_api;

// 定义复杂数据结构
#[repr(C)]
pub struct Point {
    x: f32,
    y: f32,
}

// 实现复杂函数
#[no_mangle]
pub extern "C" fn distance(p1: Point, p2: Point) -> f32 {
    let dx = p1.x - p2.x;
    let dy = p1.y - p2.y;
    (dx * dx + dy * dy).sqrt()
}

wasmtime_c_api! {
    module "geometry" {
        // 定义结构体类型
        type Point {
            x: f32,
            y: f32,
        }
        
        // 暴露复杂函数
        export "distance" fn distance(p1: Point, p2: Point) -> f32;
    }
}

// 使用方式与简单示例类似,但可以处理复杂数据结构

完整示例demo

下面是一个结合了基础用法和高级用法的完整示例:

use wasmtime_c_api_macros::wasmtime_c_api;

// 基础数学运算
#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
    a + b
}

// 几何运算
#[repr(C)]
pub struct Point {
    x: f32,
    y: f32,
}

#[no_mangle]
pub extern "C" fn distance(p1: Point, p2: Point) -> f32 {
    let dx = p1.x - p2.x;
    let dy = p1.y - p2.y;
    (dx * dx + dy * dy).sqrt()
}

// 生成所有绑定
wasmtime_c_api! {
    module "math" {
        export "add" fn add(a: i32, b: i32) -> i32;
    }
    
    module "geometry" {
        type Point {
            x: f32,
            y: f32,
        }
        export "distance" fn distance(p1: Point, p2: Point) -> f32;
    }
}

fn main() {
    let engine = wasmtime::Engine::default();
    let mut store = wasmtime::Store::new(&engine, ());
    
    // 测试数学模块
    let math_module = wasmtime::Module::new(&engine, wasmtime_c_api::math::MODULE).unwrap();
    let math_instance = wasmtime::Instance::new(&mut store, &math_module, &[]).unwrap();
    let add_func = math_instance.get_typed_func::<(i32, i32), i32>(&mut store, "add").unwrap();
    let result = add_func.call(&mut store, (5, 7)).unwrap();
    println!("5 + 7 = {}", result);
    
    // 测试几何模块
    let geo_module = wasmtime::Module::new(&engine, wasmtime_c_api::geometry::MODULE).unwrap();
    let geo_instance = wasmtime::Instance::new(&mut store, &geo_module, &[]).unwrap();
    let distance_func = geo_instance.get_typed_func::<(Point, Point), f32>(&mut store, "distance").unwrap();
    
    let p1 = Point { x: 1.0, y: 2.0 };
    let p2 = Point { x: 4.0, y: 6.0 };
    let dist = distance_func.call(&mut store, (p1, p2)).unwrap();
    println!("两点之间的距离: {}", dist);
}

许可证

Apache-2.0 WITH LLVM-exception


1 回复

以下是基于您提供的内容整理的完整示例demo:

完整示例demo

// 引入必要的库和宏
use wasmtime_c_api_macros::{wasmtime_c_api, wasmtime_export};
use wasmtime::{Engine, Store, Linker, Module, Instance};
use std::ffi::CString;

// 1. 定义一个计数器API结构体
#[wasmtime_c_api]
struct CounterApi {
    value: i32,
}

#[wasmtime_export]
impl CounterApi {
    // 构造函数
    pub fn new(initial: i32) -> Self {
        CounterApi { value: initial }
    }
    
    // 增加计数器值
    pub fn increment(&mut self) -> i32 {
        self.value += 1;
        self.value
    }
    
    // 带参数的加法操作
    pub fn add(&mut self, num: i32) -> i32 {
        self.value += num;
        self.value
    }
    
    // 获取当前值
    pub fn get(&self) -> i32 {
        self.value
    }
}

// 2. 定义字符串处理API
#[wasmtime_c_api]
struct StringApi;

#[wasmtime_export]
impl StringApi {
    // 反转字符串
    pub fn reverse(input: &str) -> String {
        input.chars().rev().collect()
    }
    
    // 处理C字符串
    pub fn process_c_string(input: *const libc::c_char) -> *mut libc::c_char {
        let c_str = unsafe { std::ffi::CStr::from_ptr(input) };
        let rust_str = c_str.to_str().unwrap();
        let processed = format!("Processed: {}", rust_str);
        CString::new(processed).unwrap().into_raw()
    }
}

// 3. 主函数集成WASM
fn main() -> wasmtime::Result<()> {
    // 创建WASM引擎和存储
    let engine = Engine::default();
    let mut store = Store::new(&engine, ());
    
    // 创建链接器并添加我们的API
    let mut linker = Linker::new(&engine);
    CounterApi::add_to_linker(&mut linker, |context| context)?;
    StringApi::add_to_linker(&mut linker, |context| context)?;
    
    // 加载并实例化WASM模块
    let module = Module::from_file(&engine, "demo.wasm")?;
    let instance = linker.instantiate(&mut store, &module)?;
    
    // 获取WASM函数并调用
    let add_func = instance.get_func(&mut store, "wasm_add").unwrap();
    let result = add_func.call(&mut store, &[5.into()])?;
    
    println!("WASM调用结果: {:?}", result);
    
    Ok(())
}

// 4. 错误处理示例
#[wasmtime_c_api]
struct FileApi;

#[wasmtime_export]
impl FileApi {
    pub fn read_file(path: &str) -> Result<String, std::io::Error> {
        std::fs::read_to_string(path)
    }
}

// 5. 回调函数示例
type MathCallback = extern "C" fn(i32, i32) -> i32;

#[wasmtime_c_api]
struct CallbackApi;

#[wasmtime_export]
impl CallbackApi {
    pub fn calculate(a: i32, b: i32, callback: MathCallback) -> i32 {
        callback(a, b)
    }
}

示例说明

  1. 计数器API

    • 展示了基本的结构体定义和方法导出
    • 包含初始化、修改和查询状态的方法
  2. 字符串处理API

    • 演示了如何处理Rust字符串和C字符串的相互转换
    • 包含字符串反转和C字符串处理的示例
  3. WASM集成

    • 展示如何将API绑定到WASM运行时
    • 包含引擎初始化、模块加载和函数调用的完整流程
  4. 错误处理

    • 演示如何将Rust的错误类型自动转换为C API可处理的格式
  5. 回调函数

    • 展示如何从Rust调用C端提供的回调函数

这个完整示例涵盖了您提供的所有关键功能点,并保持了代码的清晰性和实用性。您可以根据实际需求调整或扩展这些示例。

回到顶部