rust,使用wasmedge_sys,aot编译wasm并执行(加内存页限制,加gas限制)

依赖

[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

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;
}
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐