rust,使用wasmedge_sys,aot编译wasm并执行(加内存页限制,加gas限制)
·
rust,使用wasmedge_sys,aot编译wasm并执行(加内存页限制,加gas限制)
- wasmedge_sys https://wasmedge.github.io/wasmedge-rust-sdk/wasmedge_sys/index.html
- wasmedge文档:https://wasmedge.org/docs/zh/start/build-and-run/aot/
- rustrover 编辑器:https://www.jetbrains.com.cn/rust/
依赖
[package]
name = "t20250711_test_wasmedge_ffi"
version = "0.1.0"
edition = "2024"
[dependencies]
wasmedge-sys = { version = "0.19.4", features = ["aot", "ffi"] }
wasmedge-types = { version = "0.6.0" }
wat = { version = "1.235.0" }
#libc = "0.2.94"
代码
#![allow(non_snake_case)]
#![allow(dead_code)]
use std::borrow::Cow;
use std::ffi::CString;
use std::path::{Path, PathBuf};
use wasmedge_sys as sys;
use wasmedge_sys::{ffi as ffi};
use wasmedge_sys::{Config, WasmValue};
use wasmedge_sys::ffi::WasmEdge_ASTModuleContext;
use wasmedge_types::{CompilerOptimizationLevel, CompilerOutputFormat};
fn main() {
// 获取wasm
let watString = getWatString_fib();
// let watString = getWatString_memoryGrow();
let wasmBytes = getWasmBytes(watString.as_bytes());
// 获取配置
let config = getConfig(20).unwrap();
// 编译
let aotFilePath = aotCompile(&wasmBytes, &config);
// 执行
runWasm(&config, &aotFilePath, 99999);
// // 测试速度
// {
// // 关闭日志输出
// unsafe { ffi::WasmEdge_LogOff() };
// let mut count:u64 = 0;
// let start = std::time::Instant::now();
// loop {
// runWasm(&config, &aotFilePath, 99999);
//
// count += 1;
// if count%10000 == 0 {
// println!("耗时: {:?}, 计数={}, 速度={}/s", start.elapsed(), count, count/start.elapsed().as_secs());
// }
// }
//
// }
// 删除文件
std::fs::remove_file(&aotFilePath).unwrap();
}
/// 运行dll
fn runWasm(config:&Config, aotFilePath:&PathBuf, gasCostLimit:u64) {
// 加载
let mut astModule: *mut ffi::WasmEdge_ASTModuleContext = std::ptr::null_mut();
{
let loader = unsafe { ffi::WasmEdge_LoaderCreate(config.as_ptr()) };
// 从bytes加载
/*
{
println!("从bytes加载");
unsafe {
let bytes = wasmBytes;
let ptr = libc::malloc(bytes.as_ref().len());
let dst = ::core::slice::from_raw_parts_mut(
ptr.cast::<std::mem::MaybeUninit<u8>>(),
bytes.as_ref().len(),
);
let src = ::core::slice::from_raw_parts(
bytes.as_ref().as_ptr().cast::<std::mem::MaybeUninit<u8>>(),
bytes.as_ref().len(),
);
dst.copy_from_slice(src);
ffi::WasmEdge_LoaderParseFromBuffer(
loader,
&mut astModule,
ptr as *const u8,
bytes.as_ref().len() as u32,
);
libc::free(ptr);
}
}
*/
// 从文件加载
{
let c_path = CString::new(aotFilePath.clone().to_str().unwrap()).unwrap();
unsafe {
ffi::WasmEdge_LoaderParseFromFile(
loader,
&mut astModule,
c_path.as_ptr(),
);
}
}
unsafe { ffi::WasmEdge_LoaderDelete(loader) };
}
// 验证
{
let validator = unsafe { ffi::WasmEdge_ValidatorCreate(config.as_ptr()) };
unsafe {
ffi::WasmEdge_ValidatorValidate(
validator,
astModule,
);
}
unsafe { ffi::WasmEdge_ValidatorDelete(validator) };
}
let store = unsafe { ffi::WasmEdge_StoreCreate() };
// 运行
{
// 执行限制
let mut statistics = sys::Statistics::create().unwrap();
statistics.set_cost_limit(1);
let executor = unsafe {
let stat_ctx = statistics.as_ptr() as * mut ffi::WasmEdge_StatisticsContext;
ffi::WasmEdge_ExecutorCreate(config.as_ptr(), stat_ctx)
};
// 注册模块
let mut moduleInstance = std::ptr::null_mut();
{
let moduleName = CString::new("fibonacciModule").unwrap();
let moduleName = unsafe { ffi::WasmEdge_StringCreateByCString(moduleName.as_ptr()) };
let astModule: *const WasmEdge_ASTModuleContext = astModule as *const _;
unsafe {
ffi::WasmEdge_ExecutorRegister(
executor,
&mut moduleInstance,
store,
astModule as *const _,
moduleName,
);
}
unsafe { ffi::WasmEdge_StringDelete(moduleName) };
}
// 函数引用
let funcInstance;
{
let funcName = CString::new("fib").unwrap();
let funcName = unsafe { ffi::WasmEdge_StringCreateByCString(funcName.as_ptr()) };
funcInstance = unsafe { ffi::WasmEdge_ModuleInstanceFindFunction(moduleInstance, funcName) }; // 返回的函数不能销毁
unsafe { ffi::WasmEdge_StringDelete(funcName) };
}
// 执行
{
let params = vec![WasmValue::from_i32(10)];
let raw_params = params.into_iter().map(|x| x.as_raw()).collect::<Vec<_>>();
// 获取函数返回值大小
let returns_len:usize = 1;
// let returns_len:usize;
// {
// let funcType = unsafe { ffi::WasmEdge_FunctionInstanceGetFunctionType(funcInstance) }; // 返回的类型引用不能销毁
// let params_len = unsafe { ffi::WasmEdge_FunctionTypeGetParametersLength(funcType) } as usize;
// println!("params_len={:?}", params_len);
// returns_len = unsafe { ffi::WasmEdge_FunctionTypeGetReturnsLength(funcType) } as usize;
// println!("returns_len={:?}", returns_len);
// }
let mut returns = Vec::with_capacity(returns_len);
// 设置gas
statistics.clear();
statistics.set_cost_limit(gasCostLimit);
// 执行函数
unsafe {
ffi::WasmEdge_ExecutorInvoke(
executor,
funcInstance,
raw_params.as_ptr(),
raw_params.len() as u32,
returns.as_mut_ptr(),
returns_len as u32,
);
returns.set_len(returns_len);
}
let result = returns.into_iter().map(Into::into).collect::<Vec<WasmValue>>();
println!("返回值: {}", result[0].to_i32());
}
unsafe { ffi::WasmEdge_ModuleInstanceDelete(moduleInstance) };
unsafe { ffi::WasmEdge_ExecutorDelete(executor) };
}
unsafe { ffi::WasmEdge_ASTModuleDelete(astModule) };
unsafe { ffi::WasmEdge_StoreDelete(store) };
}
/// 获取配置
fn getConfig(maxMemoryPages:u32) -> Result<Config, Box<dyn std::error::Error>> {
let mut inner: Config = sys::Config::create()?;
// 配置提案
{
inner.mutable_globals(true); // ✅ 修改全局变量
inner.non_trap_conversions(true); // ✅ 不触发异常的数值转换操作,主要用于处理数值溢出或精度问题时避免运行时错误
inner.sign_extension_operators(true); // ✅ 增加指令集,用于扩展数字位数(例如 i64.extend8_s 将8位有符号整数扩展为64位)
inner.multi_value(true); // ✅ 让基本块可以拥有参数 (block $my_block (param i32 i32) (result i32) )
inner.bulk_memory_operations(true); // ✅ 批量内存操作提案
inner.reference_types(true); // ✅ 通过引入 anyref 类型,支持模块间复杂数据共享的提案
inner.simd(true); // ✅ SIMD指令集
inner.multi_memories(false); // ❌ 多模块内存管理机制,支持将程序拆分为多个独立模块,每个模块拥有独立的内存
inner.threads(false); // ❌ 多线程
inner.gc(false); // ❌ 垃圾回收
inner.tail_call(false); // ❌ 尾调用
inner.function_references(false); // ❌ 引入 funcref 类型作为一等公民,允许函数作为参数传递、返回值或存储在表中
inner.interpreter_mode(false); // ❌ 解释器模式
}
// 配置统计信息
{
inner.count_instructions(true); // ✅ 生成用于启用执行时间测量统计的代码
inner.measure_cost(true); // ✅ 生成用于启用执行中的 gas 测量统计的代码
inner.measure_time(true); // ✅ 生成用于启用 WebAssembly 指令计数统计的代码
}
// 配置编译选项
{
inner.set_aot_compiler_output_format(CompilerOutputFormat::Native); // 输出类型,默认wasm格式,编译好的代码放到wasm的自定义段里,文件大;native类型会生成 dll/so/dylib 文件
inner.set_aot_optimization_level(CompilerOptimizationLevel::O3); // 优化级别
inner.dump_ir(false); // ❌ 输出 LLVM IR
inner.generic_binary(false); // ❌ 生成通用二进制文件
inner.interruptible(false); // ❌ 生成支持可中断执行的二进制文件,异步且时间限制时得开启
}
// 最大内存页数
{
inner.set_max_memory_pages(maxMemoryPages); // 最大内存页数
}
return Ok(inner);
}
fn getWatString_fib() -> String {
let watStr = r#"
(module
(export "fib" (func $fib))
(func $fib (param $n i32) (result i32)
(if
(i32.lt_s
(local.get $n)
(i32.const 2)
)
(then
(return (i32.const 1))
)
)
(return
(i32.add
(call $fib
(i32.sub
(local.get $n)
(i32.const 2)
)
)
(call $fib
(i32.sub
(local.get $n)
(i32.const 1)
)
)
)
)
)
)
"#;
return String::from(watStr);
}
fn getWatString_memoryGrow() -> String {
let watStr = r#"
(module
(memory 5 100) ;; start with one memory page, and max of 10 pages
(func $memoryGrow (export "fib") (param $n i32) (result i32)
(memory.grow (local.get $n))
memory.size ;; get the memory size
return
)
)
"#;
return String::from(watStr);
}
/// 获取wasm二进制
fn getWasmBytes(watBytes: &[u8]) -> Cow<[u8]> {
// read the wasm bytes
let wasm_bytes = wat::Parser::new().parse_bytes(None, watBytes).unwrap();
return wasm_bytes;
}
/// aot 编译
fn aotCompile(wasmBytes:&Cow<[u8]>, config:&Config) -> PathBuf {
// 编译输出路径
let out_dir = std::env::current_dir().unwrap();
let aot_filename = "example_aot_fibonacci";
println!("out_dir={:?}, aot_filename={}", out_dir, aot_filename);
// 编译
let aotFilePath = getAotFilePath(out_dir, aot_filename);
{
let compiler = sys::Compiler::create(Some(&config)).unwrap();
compiler.compile_from_bytes(&wasmBytes, &aotFilePath).unwrap();
println!("aotFilePath={:?}", aotFilePath);
}
return aotFilePath;
}
/// 获取aot编译后的文件路径
fn getAotFilePath(out_dir: impl AsRef<Path>, filename: impl AsRef<str>) -> PathBuf {
#[cfg(target_os = "linux")]
let extension = "so";
#[cfg(target_os = "macos")]
let extension = "dylib";
#[cfg(target_os = "windows")]
let extension = "dll";
let aot_file = out_dir
.as_ref()
.join(format!("{}.{}", filename.as_ref(), extension));
return aot_file;
}

如果找不到 libclang.so
- win安装clang https://www.cnblogs.com/RioTian/p/17758813.html
- 下载地址:https://github.com/llvm/llvm-project/releases
迅雷倒是能通过链接直接下载 https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.7/clang+llvm-20.1.7-x86_64-pc-windows-msvc.tar.xz
解压后配置环境变量
LIBCLANG_PATH=C:\Program Files\clang+llvm-20.1.7-x86_64-pc-windows-msvc\lib
20250725 增加错误处理,修复内存释放
[package]
name = "t20250716_wasmedge_test"
version = "0.1.0"
edition = "2024"
[dependencies]
wasmedge-sys = { version = "0.19.4", features = ["aot", "ffi"] }
wasmedge-types = { version = "0.6.0" }
wat = { version = "1.235.0" }
#libc = "0.2.94"
thiserror = "1.0.69"
anyhow = "1.0.69"
# 日志库
tracing = "0.1"
tracing-subscriber = "0.3.0"
# 随机数
rand = { version = "0.9.1", features = [] }
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(dead_code)]
use anyhow::Error;
use tracing::{warn, info};
use std::borrow::Cow;
use std::ffi::CString;
use std::fmt::{Debug, Display};
use std::path::{Path, PathBuf};
use wasmedge_sys as sys;
use wasmedge_sys::{ffi as ffi, Function};
use wasmedge_sys::{Config, WasmValue};
use wasmedge_sys::ffi::{WasmEdge_ConfigureContext, WasmEdge_Result, WasmEdge_ResultGetCode, WasmEdge_ResultOK};
use wasmedge_sys::instance::function::AsFunc;
use wasmedge_types::{CompilerOptimizationLevel, CompilerOutputFormat, FuncType, ValType};
fn main() -> Result<(), Error> {
initLog(
// tracing::Level::ERROR
tracing::Level::INFO
); // 初始化日志级别
// 获取wasm
let watString = getWatString_fib();
// let watString = getWatString_memoryGrow();
let wasmBytes = getWasmBytes(watString.as_bytes())?;
// 获取配置
let config = getConfig(10)?;
// 编译
let aotFilePath = getAotFilePath(std::env::current_dir()?, "example_aot_fibonacci");
aotCompile(&wasmBytes, &config, &aotFilePath)?;
// 执行
runWasm(&config, &aotFilePath, 9999)?;
// // 测试速度
// {
// // 关闭日志输出
// unsafe { ffi::WasmEdge_LogOff() };
// let mut count:u64 = 0;
// let start = std::time::Instant::now();
// let mut rng = rand::rng();
// loop {
// match runWasm(&config, &aotFilePath, rng.random_range(1000..99999)) {
// Ok(_) => {}
// Err(e) => {
// warn!("error: {}", e);
// }
// };
//
// count += 1;
// if count%10000 == 0 {
// println!("耗时: {:?}, 计数={}, 速度={}/s", start.elapsed(), count, count/start.elapsed().as_secs());
// }
// }
//
// }
// 删除文件
std::fs::remove_file(&aotFilePath)?;
return Ok(());
}
/// 初始化日志
fn initLog(level: tracing::Level) {
// 初始化日志记录
let subscriber = tracing_subscriber::FmtSubscriber::builder()
.with_max_level(level)
.finish();
tracing::subscriber::set_global_default(subscriber)
.expect("setting default tracing subscriber failed");
}
/// wasmedge的一些错误
#[derive(Debug, thiserror::Error)]
enum MyWasmedgeError {
#[error("编译wat失败: {0}")]
编译wat失败(wat::Error),
#[error("编译wasm失败: {0}")]
编译wasm失败(String),
#[error("创建字符串失败: {0}")]
创建字符串失败(String),
#[error("wasmedge返回值检查失败: {0}")]
wasmedge返回值检查失败(String),
#[error("获取wasmedge配置失败: {0}")]
wasmedge获取配置失败(String),
#[error("wasmedge运行失败: {0}")]
wasmedge运行失败(String),
}
// 定义一堆结构体,方便drop的管理
/// ASTModule
struct MyAstModule {
inner: InnerAstModule,
}
impl MyAstModule {
fn new(ctx: *mut ffi::WasmEdge_ASTModuleContext) -> Self {
return Self {
inner: InnerAstModule(ctx)
}
}
}
struct InnerAstModule(*mut ffi::WasmEdge_ASTModuleContext);
impl Drop for MyAstModule {
fn drop(&mut self) { unsafe { ffi::WasmEdge_ASTModuleDelete(self.inner.0) }; }
}
/// Store
struct MyStore {
inner: InnerStore,
}
impl MyStore {
fn new() -> Result<Self, MyWasmedgeError> {
let store = unsafe { ffi::WasmEdge_StoreCreate() };
if store.is_null() {
return Err(MyWasmedgeError::wasmedge运行失败(String::from("store创建失败")))
} else {
return Ok(MyStore { inner: InnerStore(store) })
}
}
}
struct InnerStore(*mut ffi::WasmEdge_StoreContext);
impl Drop for MyStore {
fn drop(&mut self) { unsafe { ffi::WasmEdge_StoreDelete(self.inner.0) } }
}
/// Executor
struct MyExecutor {
inner: InnerExecutor,
}
impl MyExecutor {
fn new(config: *const WasmEdge_ConfigureContext, statistics: *const ffi::WasmEdge_StatisticsContext) -> Result<Self, MyWasmedgeError> {
let executor = unsafe {
ffi::WasmEdge_ExecutorCreate(config, statistics as *mut ffi::WasmEdge_StatisticsContext)
};
if executor.is_null() {
return Err(MyWasmedgeError::wasmedge运行失败(String::from("executor创建失败")))
} else {
return Ok(MyExecutor { inner: InnerExecutor(executor) })
}
}
}
struct InnerExecutor(*mut ffi::WasmEdge_ExecutorContext);
impl Drop for MyExecutor {
fn drop(&mut self) { unsafe { ffi::WasmEdge_ExecutorDelete(self.inner.0) } }
}
/// Module
struct MyModule {
inner: InnerModule,
}
impl MyModule {
fn new(ctx: *mut ffi::WasmEdge_ModuleInstanceContext) -> Result<Self, MyWasmedgeError> {
if ctx.is_null() {
return Err(MyWasmedgeError::wasmedge运行失败(String::from("module创建失败")))
} else {
return Ok(MyModule { inner: InnerModule(ctx) })
}
}
}
struct InnerModule(*mut ffi::WasmEdge_ModuleInstanceContext);
impl Drop for MyModule {
fn drop(&mut self) { unsafe { ffi::WasmEdge_ModuleInstanceDelete(self.inner.0) }; }
}
/// String
struct MyString {
inner: InnerString,
}
impl MyString {
fn new(string:&str) -> Result<Self, MyWasmedgeError> {
let cstring = CString::new(string)
.map_err(|e|MyWasmedgeError::创建字符串失败(format!("创建字符串失败: {}", e)))?;
let wasmString = unsafe { ffi::WasmEdge_StringCreateByCString(cstring.as_ptr()) };
return Ok(MyString {
inner: InnerString(wasmString),
});
}
}
struct InnerString(ffi::WasmEdge_String);
impl Drop for MyString {
fn drop(&mut self) { unsafe { ffi::WasmEdge_StringDelete(self.inner.0) }; }
}
/// Loader
struct MyLoader {
inner: InnerLoader,
}
impl MyLoader {
fn new(config: *const WasmEdge_ConfigureContext,) -> Result<MyLoader, MyWasmedgeError> {
let loader = unsafe { ffi::WasmEdge_LoaderCreate(config) };
if loader.is_null() {
return Err(MyWasmedgeError::创建字符串失败(String::from("loader创建失败")))
} else {
return Ok(MyLoader { inner: InnerLoader(loader) })
}
}
}
struct InnerLoader(*mut ffi::WasmEdge_LoaderContext);
impl Drop for MyLoader {
fn drop(&mut self) { unsafe { ffi::WasmEdge_LoaderDelete(self.inner.0) }; }
}
/// Validate
struct MyValidate {
inner: InnerValidate,
}
impl MyValidate {
fn new(config: *const WasmEdge_ConfigureContext,) -> Result<MyValidate, MyWasmedgeError> {
let validator = unsafe { ffi::WasmEdge_ValidatorCreate(config) };
if validator.is_null() {
return Err(MyWasmedgeError::wasmedge运行失败(String::from("validator创建失败")))
} else {
return Ok(MyValidate { inner: InnerValidate(validator) })
}
}
}
struct InnerValidate(*mut ffi::WasmEdge_ValidatorContext);
impl Drop for MyValidate {
fn drop(&mut self) { unsafe { ffi::WasmEdge_ValidatorDelete(self.inner.0) }; }
}
/// 检查 WasmEdge_Result 是否错误
fn check(result: WasmEdge_Result, msg: &str) -> Result<(), Error> {
if unsafe { WasmEdge_ResultOK(result) } {
return Ok(());
}
let code = unsafe { WasmEdge_ResultGetCode(result) } as ffi::WasmEdge_ErrCode; // 错误码
let category = unsafe { ffi::WasmEdge_ResultGetCategory(result) }; // 错误类别
match category {
ffi::WasmEdge_ErrCategory_UserLevelError => Err(Error::new(MyWasmedgeError::wasmedge返回值检查失败(format!("{}, 用户自定义错误码={}", msg, code)))),
ffi::WasmEdge_ErrCategory_WASM => Err(Error::new(MyWasmedgeError::wasmedge返回值检查失败(format!("{}, wasm错误码={}", msg, code)))),
_ => Err(Error::new(MyWasmedgeError::wasmedge返回值检查失败(format!("{}, 未知的错误类别={}", msg, category)))),
}
}
/// 运行dll
fn runWasm(config:&Config, aotFilePath:&PathBuf, gasCostLimit:u64) -> Result<(), Error> {
// 给error加上描述
fn getError<T: Display>(msg: &str, e:T) -> MyWasmedgeError { MyWasmedgeError::wasmedge运行失败(format!("{}: {}", msg, e)) }
fn newError(msg: &str) -> Error { Error::new(MyWasmedgeError::wasmedge运行失败(String::from(msg))) }
// 加载
let astModule: MyAstModule;
{
// 从文件加载
let aotFilePath = aotFilePath.to_str().ok_or_else(|| {MyWasmedgeError::wasmedge运行失败(String::from("文件路径为空"))})?;
let c_path = CString::new(aotFilePath)
.map_err(|e|getError("文件路径异常", e))?;
// 加载到模块
let mut astModuleInner = std::ptr::null_mut();
let loader = MyLoader::new(config.as_ptr())?;
check(unsafe {
ffi::WasmEdge_LoaderParseFromFile(
loader.inner.0,
&mut astModuleInner, // 创建 astModule
c_path.as_ptr(),
)
}, "astModule创建失败")?;
astModule = MyAstModule {
inner: InnerAstModule(astModuleInner),
};
}
// 验证
{
let validator = MyValidate::new(config.as_ptr())?;
check(unsafe {
ffi::WasmEdge_ValidatorValidate(
validator.inner.0,
astModule.inner.0,
)
}, "wasm验证失败")?;
}
let store = MyStore::new()?;
// 运行
let result: Vec<WasmValue>;
{
// 执行限制
let mut statistics = sys::Statistics::create()
.map_err(|e| { getError("创建Statistics失败", e) })?; // 不用销毁
statistics.set_cost_limit(1);
// 执行器
let executor = MyExecutor::new(config.as_ptr(), statistics.as_ptr())?;
// 注册host模块
let hostModule: MyModule;
{
let hostData = Box::new(HostData {
name: String::from("name"),
age: 18,
});
// 创建host模块,并带上host数据
{
let hostModule_name = MyString::new("hostModule")?;
let moduleInstance = unsafe {
ffi::WasmEdge_ModuleInstanceCreateWithData(
hostModule_name.inner.0,
Box::leak(hostData) as *mut _ as *mut std::ffi::c_void, // hostData,手动造成内存泄漏,交由wasmedge管理
Some(import_data_finalizer::<HostData>), // 释放hostData的函数
)
};
hostModule = MyModule::new(moduleInstance)?;
}
// host模块内注册函数
{
let funcName = MyString::new("hostAdd")?;
let funcType = FuncType::new(vec![ValType::I32, ValType::I32], vec![ValType::I32]);
let hostData = unsafe { &mut *(ffi::WasmEdge_ModuleInstanceGetHostData(hostModule.inner.0) as *mut HostData) };
let hostFuncCost = 10;
let hostAddFunc = unsafe {
Function::create_sync_func(&funcType, hostAdd, hostData, hostFuncCost) // 注册host函数,并附带host数据、gas消耗
}.map_err(|e|getError("注册host函数失败", e))?;
unsafe {
ffi::WasmEdge_ModuleInstanceAddFunction(
hostModule.inner.0,
funcName.inner.0,
hostAddFunc.get_func_raw(),
);
}
std::mem::forget(hostAddFunc); // 函数交由wasmedge释放,rust不能释放
}
// 注册host模块
{
check(unsafe {
ffi::WasmEdge_ExecutorRegisterImport(
executor.inner.0,
store.inner.0,
hostModule.inner.0,
)
}, "注册host模块失败")?;
}
}
// 加载并注册模块
let module: MyModule;
{
let mut moduleInstance = std::ptr::null_mut();
let moduleName = MyString::new("moduleName")?;
unsafe {
check(ffi::WasmEdge_ExecutorRegister(
executor.inner.0,
&mut moduleInstance,
store.inner.0,
astModule.inner.0 as *const _,
moduleName.inner.0,
), "注册模块失败")?;
}
module = MyModule::new(moduleInstance)?;
}
// 函数引用
let funcInstance;
{
let funcName = MyString::new("fib")?;
funcInstance = unsafe { ffi::WasmEdge_ModuleInstanceFindFunction(module.inner.0, funcName.inner.0) }; // 返回的函数不能销毁
}
// 执行
{
let params = vec![WasmValue::from_i32(10)];
let raw_params = params.into_iter().map(|x| x.as_raw()).collect::<Vec<_>>();
// 获取函数返回值大小
let returns_len:usize;
{
let funcType = unsafe { ffi::WasmEdge_FunctionInstanceGetFunctionType(funcInstance) }; // 返回的类型引用不能销毁
// let params_len = unsafe { ffi::WasmEdge_FunctionTypeGetParametersLength(funcType) } as usize;
returns_len = unsafe { ffi::WasmEdge_FunctionTypeGetReturnsLength(funcType) } as usize;
// println!("params_len={:?},returns_len={:?}", params_len, returns_len);
}
let mut returns = Vec::with_capacity(returns_len);
// 设置gas
statistics.clear();
statistics.set_cost_limit(gasCostLimit);
// 执行函数
unsafe {
check(ffi::WasmEdge_ExecutorInvoke(
executor.inner.0,
funcInstance,
raw_params.as_ptr(),
raw_params.len() as u32,
returns.as_mut_ptr(),
returns_len as u32,
), "执行函数失败")?;
returns.set_len(returns_len);
}
result = returns.into_iter().map(Into::into).collect::<Vec<WasmValue>>();
info!("返回值: {}", result[0].to_i32());
}
}
return Ok(());
}
/// 获取配置
/// 内存超过限制只是不分配,但不中止运行
fn getConfig(maxMemoryPages:u32) -> Result<Config, MyWasmedgeError> {
let mut config: Config = sys::Config::create()
.map_err(|e|MyWasmedgeError::wasmedge获取配置失败(format!("创建wasmedge配置失败: {}", e)))?;
// 配置提案
{
config.mutable_globals(true); // ✅ 修改全局变量
config.non_trap_conversions(true); // ✅ 不触发异常的数值转换操作,主要用于处理数值溢出或精度问题时避免运行时错误
config.sign_extension_operators(true); // ✅ 增加指令集,用于扩展数字位数(例如 i64.extend8_s 将8位有符号整数扩展为64位)
config.multi_value(true); // ✅ 让基本块可以拥有参数 (block $my_block (param i32 i32) (result i32) )
config.bulk_memory_operations(true); // ✅ 批量内存操作提案
config.reference_types(true); // ✅ 通过引入 anyref 类型,支持模块间复杂数据共享的提案
config.simd(true); // ✅ SIMD指令集
config.multi_memories(false); // ❌ 多模块内存管理机制,支持将程序拆分为多个独立模块,每个模块拥有独立的内存
config.threads(false); // ❌ 多线程
config.gc(false); // ❌ 垃圾回收
config.tail_call(false); // ❌ 尾调用
config.function_references(false); // ❌ 引入 funcref 类型作为一等公民,允许函数作为参数传递、返回值或存储在表中
config.interpreter_mode(false); // ❌ 解释器模式
}
// 配置统计信息
{
config.count_instructions(true); // ✅ 生成用于启用执行时间测量统计的代码
config.measure_cost(true); // ✅ 生成用于启用执行中的 gas 测量统计的代码
config.measure_time(true); // ✅ 生成用于启用 WebAssembly 指令计数统计的代码
}
// 配置编译选项
{
config.set_aot_compiler_output_format(CompilerOutputFormat::Native); // 输出类型,默认wasm格式,编译好的代码放到wasm的自定义段里,文件大;native类型会生成 dll/so/dylib 文件
config.set_aot_optimization_level(CompilerOptimizationLevel::O3); // 优化级别
config.dump_ir(false); // ❌ 输出 LLVM IR
config.generic_binary(false); // ❌ 生成通用二进制文件
config.interruptible(false); // ❌ 生成支持可中断执行的二进制文件,异步且时间限制时得开启
}
// 最大内存页数
{
config.set_max_memory_pages(maxMemoryPages); // 最大内存页数
}
return Ok(config);
}
/// 计算斐波那契数
fn getWatString_fib() -> String {
let watStr = r#"
(module
(import "hostModule" "hostAdd" (func $hostAdd (param i32 i32) (result i32)))
(export "fib" (func $fib))
(func $fib (param $n i32) (result i32)
(if
(i32.lt_s
(local.get $n)
(i32.const 2)
)
(then
(return (i32.const 1))
)
)
(return
(call $hostAdd ;; 调用host的函数
(call $fib
(i32.sub
(local.get $n)
(i32.const 2)
)
)
(call $fib
(i32.sub
(local.get $n)
(i32.const 1)
)
)
)
)
)
)
"#;
return String::from(watStr);
}
/// host的数据
struct HostData {
name: String,
age: i32,
}
unsafe extern "C" fn import_data_finalizer<T>(ptr: *mut std::os::raw::c_void) {
let box_data: Box<T> = unsafe { Box::from_raw(ptr as _) };
std::mem::drop(box_data)
}
/// host的add函数
fn hostAdd(
_: &mut HostData,
_inst: &mut sys::Instance,
_caller: &mut sys::CallingFrame,
input: Vec<WasmValue>,
) -> Result<Vec<WasmValue>, wasmedge_types::error::CoreError> {
// 检查是不是俩参数
if input.len() != 2 {
return Err(wasmedge_types::error::CoreError::Execution(
wasmedge_types::error::CoreExecutionError::FuncSigMismatch, // 函数签名不对
));
}
// 第一个参数,并检查类型
let a = if input[0].ty() == wasmedge_types::ValType::I32 {
input[0].to_i32()
} else {
return Err(wasmedge_types::error::CoreError::Execution(
wasmedge_types::error::CoreExecutionError::FuncSigMismatch,
));
};
// 第二个参数,并检查类型
let b = if input[1].ty() == wasmedge_types::ValType::I32 {
input[1].to_i32()
} else {
return Err(wasmedge_types::error::CoreError::Execution(
wasmedge_types::error::CoreExecutionError::FuncSigMismatch,
));
};
let c = a + b; // 执行加法
// println!("{a} + {b} => {c}");
Ok(vec![WasmValue::from_i32(c)]) // 返回
}
/// 测试内存页限制
fn getWatString_memoryGrow() -> String {
let watStr = r#"
(module
(memory 5 100) ;; start with one memory page, and max of 10 pages
(func $memoryGrow (export "fib") (param $n i32) (result i32)
(memory.grow (local.get $n))
memory.size ;; get the memory size
return
)
)
"#;
return String::from(watStr);
}
/// wat编译成wasm
fn getWasmBytes(watBytes: &[u8]) -> Result<Cow<[u8]>, Error> {
let wasm_bytes = wat::Parser::new().parse_bytes(None, watBytes).map_err(MyWasmedgeError::编译wat失败)?;
return Ok(wasm_bytes);
}
/// aot 编译
fn aotCompile(wasmBytes:&Cow<[u8]>, config:&Config, aotFilePath:&PathBuf) -> Result<(), MyWasmedgeError> {
let compiler = sys::Compiler::create(Some(&config))
.map_err(|e|MyWasmedgeError::编译wasm失败(format!("创建编译器失败: {}", e)))?;
compiler.compile_from_bytes(&wasmBytes, &aotFilePath)
.map_err(|e|MyWasmedgeError::编译wasm失败(format!("编译失败: {}", e)))?;
info!("aot编译成功={:?}", aotFilePath);
return Ok(());
}
/// 获取aot编译后的文件路径
fn getAotFilePath(out_dir: impl AsRef<Path>, filename: impl AsRef<str>) -> PathBuf {
#[cfg(target_os = "linux")]
let extension = "so";
#[cfg(target_os = "macos")]
let extension = "dylib";
#[cfg(target_os = "windows")]
let extension = "dll";
let aot_file = out_dir
.as_ref()
.join(format!("{}.{}", filename.as_ref(), extension));
return aot_file;
}
更多推荐



所有评论(0)