Rust WebAssembly运行时Wasmtime C API实现库wasmtime-c-api-impl的使用,支持高效WASM模块加载与跨语言交互
Rust WebAssembly运行时Wasmtime C API实现库wasmtime-c-api-impl的使用,支持高效WASM模块加载与跨语言交互
API文档
在C/C++项目中使用
使用预构建的静态或动态库
Wasmtime提供了各种架构和操作系统的预构建二进制文件,包括静态库、动态库和头文件。
从源码构建Wasmtime C/C++ API
要使用Wasmtime的C/C++ API,需要安装CMake和Rust工具链。
从Wasmtime仓库根目录运行以下命令:
$ cmake -S crates/c-api -B target/c-api --install-prefix "$(pwd)/artifacts"
$ cmake --build target/c-api
$ cmake --install target/c-api
构建完成后会生成以下文件:
artifacts/lib/libwasmtime.{a,lib}
: 静态库artifacts/lib/libwasmtime.{so,dylib,dll}
: 动态库artifacts/include/**.{h,hh}
: 头文件
在Rust项目中使用
如果您的Rust crate需要绑定使用Wasmtime的C/C++库,可以通过Cargo链接Wasmtime C API。
- 在
Cargo.toml
中添加依赖:
[dependencies]
wasmtime-c-api = { version = "16.0.0", package = "wasmtime-c-api-impl" }
- 在
build.rs
中添加Wasmtime C头文件路径:
fn main() {
let mut cfg = cc::Build::new();
// 添加Wasmtime头文件路径
cfg
.include(std::env::var("DEP_WASMTIME_C_API_INCLUDE").unwrap());
// 编译您的C代码
cfg
.file("src/your_c_code.c")
.compile("your_library");
}
完整示例
下面是一个完整的Rust项目示例,演示如何使用wasmtime-c-api-impl加载和运行WASM模块:
首先在Cargo.toml中添加依赖:
[dependencies]
wasmtime-c-api = { version = "16.0.0", package = "wasmtime-c-api-impl" }
然后创建一个Rust项目:
use wasmtime_c_api::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 初始化Wasmtime引擎
let engine = wasm_engine_new();
// 创建存储
let store = wasm_store_new(engine, std::ptr::null_mut());
// 加载WASM模块
let wasm = include_bytes!("example.wasm");
let module = wasm_module_new(store, wasm.as_ptr() as *const u8, wasm.len())?;
// 创建实例
let instance = wasm_instance_new(store, module, std::ptr::null_mut(), 0, std::ptr::null_mut())?;
// 获取导出函数
let exports = wasm_instance_exports(instance);
let func = wasm_extern_as_func(wasm_extern_vec_get(exports, 0));
// 调用WASM函数
let params = [wasm_val_i32(5)];
let mut results = [wasm_val_uninit()];
wasm_func_call(func, params.as_ptr(), results.as_mut_ptr())?;
// 获取结果
let result = unsafe { results[0].of.i32 };
println!("WASM函数返回: {}", result);
// 清理资源
wasm_instance_delete(instance);
wasm_module_delete(module);
wasm_store_delete(store);
wasm_engine_delete(engine);
Ok(())
}
这个示例展示了如何:
- 初始化Wasmtime引擎
- 加载WASM模块
- 创建实例
- 调用WASM函数
- 获取返回值
- 清理资源
通过wasmtime-c-api-impl,您可以轻松地在Rust项目中集成Wasmtime的C API功能,实现高效的WASM模块加载和跨语言交互。
1 回复
Rust WebAssembly运行时Wasmtime C API实现库wasmtime-c-api-impl使用指南
完整示例Demo
下面是一个完整的Rust示例,展示如何使用wasmtime-c-api-impl加载WASM模块并调用其中的函数:
use wasmtime_c_api_impl::{
wasm_engine_new, wasm_store_new, wasm_byte_vec_new, wasm_module_new,
wasm_instance_new, wasm_instance_exports, wasm_extern_as_func,
wasm_func_call, wasm_val_t, wasm_valkind_enum,
wasm_module_delete, wasm_byte_vec_delete, wasm_instance_delete,
wasm_store_delete, wasm_engine_delete
};
fn main() {
// 1. 初始化引擎和存储
unsafe {
let engine = wasm_engine_new();
let store = wasm_store_new(engine);
// 2. 加载和编译WASM模块
// 示例WASM模块(一个简单的加法函数)
let wasm_bytes: Vec<u8> = vec![
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,
// ... 实际的WASM字节码
];
let mut binary = wasm_byte_vec_new(wasm_bytes.len(), wasm_bytes.as_ptr() as *mut _);
let module = wasm_module_new(store, &binary);
// 3. 创建实例并调用函数
let instance = wasm_instance_new(store, module, std::ptr::null(), std::ptr::null_mut());
// 获取导出函数
let exports = wasm_instance_exports(instance);
let func = wasm_extern_as_func(*exports.offset(0)); // 假设第一个导出是add函数
// 准备参数和结果
let mut params = [
wasm_val_t { kind: wasm_valkind_enum::WASM_I32, of: wasm_val_t__bindgen_ty_1 { i32: 5 } },
wasm_val_t { kind: wasm_valkind_enum::WASM_I32, of: wasm_val_t__bindgen_ty_1 { i32: 7 } }
];
let mut results = [wasm_val_t { kind: wasm_valkind_enum::WASM_I32, of: wasm_val_t__bindgen_ty_1 { i32: 0 } }];
// 调用函数
if wasm_func_call(func, params.as_mut_ptr(), results.as_mut_ptr()).is_null() {
println!("函数调用成功,结果: {}", results[0].of.i32);
} else {
println!("函数调用失败");
}
// 清理资源
wasm_instance_delete(instance);
wasm_module_delete(module);
wasm_byte_vec_delete(&mut binary);
wasm_store_delete(store);
wasm_engine_delete(engine);
}
}
C语言调用完整示例
#include <stdio.h>
#include <wasm.h>
#include <wasmtime.h>
int main() {
// 初始化引擎和存储
wasm_engine_t* engine = wasm_engine_new();
wasm_store_t* store = wasm_store_new(engine);
// 加载WASM模块
FILE* file = fopen("add.wasm", "rb");
if (!file) {
printf("无法打开WASM文件\n");
return 1;
}
fseek(file, 0, SEEK_END);
size_t file_size = ftell(file);
fseek(file, 0, SEEK_SET);
wasm_byte_vec_t wasm;
wasm_byte_vec_new_uninitialized(&wasm, file_size);
if (fread(wasm.data, file_size, 1, file) != 1) {
printf("读取WASM文件失败\n");
fclose(file);
return 1;
}
fclose(file);
// 编译模块
wasm_module_t* module = wasm_module_new(store, &wasm);
if (!module) {
printf("编译WASM模块失败\n");
wasm_byte_vec_delete(&wasm);
wasm_store_delete(store);
wasm_engine_delete(engine);
return 1;
}
// 创建实例
wasm_instance_t* instance = wasm_instance_new(store, module, NULL, NULL);
if (!instance) {
printf("创建实例失败\n");
wasm_module_delete(module);
wasm_byte_vec_delete(&wasm);
wasm_store_delete(store);
wasm_engine_delete(engine);
return 1;
}
// 获取导出函数
wasm_extern_vec_t exports;
wasm_instance_exports(instance, &exports);
if (exports.size == 0) {
printf("没有找到导出函数\n");
wasm_instance_delete(instance);
wasm_module_delete(module);
wasm_byte_vec_delete(&wasm);
wasm_store_delete(store);
wasm_engine_delete(engine);
return 1;
}
wasm_func_t* func = wasm_extern_as_func(exports.data[0]);
if (!func) {
printf("第一个导出不是函数\n");
wasm_instance_delete(instance);
wasm_module_delete(module);
wasm_byte_vec_delete(&wasm);
wasm_store_delete(store);
wasm_engine_delete(engine);
return 1;
}
// 准备参数和结果
wasm_val_t params[2] = { WASM_I32_VAL(3), WASM_I32_VAL(4) };
wasm_val_t results[1];
// 调用函数
if (wasm_func_call(func, params, results)) {
printf("函数调用失败\n");
} else {
printf("3 + 4 = %d\n", results[0].of.i32);
}
// 清理资源
wasm_instance_delete(instance);
wasm_module_delete(module);
wasm_byte_vec_delete(&wasm);
wasm_store_delete(store);
wasm_engine_delete(engine);
return 0;
}
高级功能完整示例
use wasmtime_c_api_impl::{
wasm_config_new, wasm_engine_new_with_config, wasmtime_config_debug_info_set,
wasmtime_config_parallel_compilation_set, wasm_store_new, wasm_byte_vec_new,
wasm_module_new, wasm_instance_new, wasm_instance_exports, wasm_extern_as_func,
wasm_func_call, wasm_val_t, wasm_valkind_enum, wasm_functype_new, wasm_func_new,
wasm_module_delete, wasm_byte_vec_delete, wasm_instance_delete, wasm_store_delete,
wasm_engine_delete
};
unsafe {
// 1. 配置引擎
let config = wasm_config_new();
wasmtime_config_debug_info_set(config, true); // 启用调试信息
wasmtime_config_parallel_compilation_set(config, true); // 启用并行编译
let engine = wasm_engine_new_with_config(config);
let store = wasm_store_new(engine);
// 2. 加载模块
let wasm_bytes = wat::parse_str("
(module
(func $add (param i32 i32) (result i32)
local.get 0
local.get 1
i32.add)
(export \"add\" (func $add))
)
").unwrap();
let mut binary = wasm_byte_vec_new(wasm_bytes.len(), wasm_bytes.as_ptr() as *mut _);
let module = wasm_module_new(store, &binary);
// 3. 链接自定义主机函数
extern "C" fn host_multiply(
args: *const wasm_val_t,
results: *mut wasm_val_t,
) -> *mut std::ffi::c_void {
let a = unsafe { (*args.offset(0)).of.i32 };
let b = unsafe { (*args.offset(1)).of.i32 };
unsafe { (*results.offset(0)).of.i32 = a * b };
std::ptr::null_mut()
}
let mut params = [wasm_valkind_enum::WASM_I32, wasm_valkind_enum::WASM_I32];
let mut results = [wasm_valkind_enum::WASM_I32];
let type_ = wasm_functype_new(
params.as_mut_ptr(), params.len(),
results.as_mut_ptr(), results.len()
);
let host_func = wasm_func_new(store, type_, host_multiply);
// 4. 创建实例并调用函数
let instance = wasm_instance_new(store, module, std::ptr::null(), std::ptr::null_mut());
let exports = wasm_instance_exports(instance);
let add_func = wasm_extern_as_func(*exports.offset(0));
let mut add_params = [
wasm_val_t { kind: wasm_valkind_enum::WASM_I32, of: wasm_val_t__bindgen_ty_1 { i32: 6 } },
wasm_val_t { kind: wasm_valkind_enum::WASM_I32, of: wasm_val_t__bindgen_ty_1 { i32: 7 } }
];
let mut add_results = [wasm_val_t { kind: wasm_valkind_enum::WASM_I32, of: wasm_val_t__bindgen_ty_1 { i32: 0 } }];
if wasm_func_call(add_func, add_params.as_mut_ptr(), add_results.as_mut_ptr()).is_null() {
println!("6 + 7 = {}", add_results[0].of.i32);
}
// 调用主机函数
let mut multiply_params = [
wasm_val_t { kind: wasm_valkind_enum::WASM_I32, of: wasm_val_t__bindgen_ty_1 { i32: 6 } },
wasm_val_t { kind: wasm_valkind_enum::WASM_I32, of: wasm_val_t__bindgen_ty_1 { i32: 7 } }
];
let mut multiply_results = [wasm_val_t { kind: wasm_valkind_enum::WASM_I32, of: wasm_val_t__bindgen_ty_1 { i32: 0 } }];
if wasm_func_call(host_func, multiply_params.as_mut_ptr(), multiply_results.as_mut_ptr()).is_null() {
println!("6 * 7 = {}", multiply_results[0].of.i32);
}
// 清理资源
wasm_instance_delete(instance);
wasm_module_delete(module);
wasm_byte_vec_delete(&mut binary);
wasm_store_delete(store);
wasm_engine_delete(engine);
}
这些完整示例展示了wasmtime-c-api-impl库的主要功能,包括基本使用、跨语言调用和高级功能配置。使用时请根据实际需求调整代码,并注意资源管理和线程安全等问题。