Repository: WasmEdge/wasmedge-rust-sdk (language: rust)

Issue:
Unsafe `data` parameters
The unsafe `data` parameters are used in the following methods:

```rust
// wasmedge_sys::Function::create_sync_func
pub fn create_sync_func<T>(
        ty: &FuncType,
        real_fn: BoxedFn,
        data: Option<&mut T>,
        cost: u64,
    ) -> WasmEdgeResult<Self> { ... }

// wasmedge_sdk::Func::wrap_func
pub fn wrap_func<Args, Rets, T>(
        real_func: impl Fn(
                CallingFrame,
                Vec<WasmValue>,
                *mut std::os::raw::c_void,
            ) -> Result<Vec<WasmValue>, HostFuncError>
            + Send
            + Sync
            + 'static,
        data: Option<&mut T>,
    ) -> WasmEdgeResult<Self> { ... }
```


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml
index 07a6abf38..66a861452 100644
--- a/.github/workflows/ci-build.yml
+++ b/.github/workflows/ci-build.yml
@@ -73,6 +73,7 @@ jobs:
         run: |
           rustup target add wasm32-wasi
           rustc async_hello.rs --target=wasm32-wasi -o async_hello.wasm
+          rustc hello.rs --target=wasm32-wasi -o hello.wasm
 
       - name: Test Rust SDK
         run: |
@@ -140,6 +141,7 @@ jobs:
         run: |
           rustup target add wasm32-wasi
           rustc async_hello.rs --target=wasm32-wasi -o async_hello.wasm
+          rustc hello.rs --target=wasm32-wasi -o hello.wasm
 
       - name: Test Rust SDK
         run: |
diff --git a/Cargo.toml b/Cargo.toml
index 83a25fe6f..433a789b3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,23 +8,32 @@ license = "Apache-2.0"
 name = "wasmedge-sdk"
 readme = "README.md"
 repository = "https://github.com/WasmEdge/WasmEdge/blob/master/bindings/rust/wasmedge-sdk"
-version = "0.10.1"
+version = "0.11.0-dev"
 
 [dependencies]
 anyhow = "1.0"
 num-derive = "0.3"
 num-traits = "0.2"
 thiserror = "1.0.30"
-wasmedge-macro = {path = "crates/wasmedge-macro", version = "0.5"}
-wasmedge-sys = {path = "crates/wasmedge-sys", version = "0.15", default-features = false}
-wasmedge-types = {path = "crates/wasmedge-types", version = "0.4"}
+wasmedge-macro.workspace = true
+wasmedge-sys = {path = "crates/wasmedge-sys", version = "0.16", default-features = false}
+wasmedge-types.workspace = true
+cfg-if.workspace = true
 
 [workspace.dependencies]
+cfg-if = "1.0.0"
 wat = "=1.0.67"
+async-wasi = {path = "crates/async-wasi", version = "=0.0.3"}
+wasmedge-macro = {path = "crates/wasmedge-macro", version = "0.5"}
+wasmedge-types = {path = "crates/wasmedge-types", version = "0.4"}
+parking_lot = "0.12.1"
+
+[target.'cfg(target_os = "linux")'.dependencies]
+async-wasi = {workspace = true, optional = true}
 
 [features]
 aot = ["wasmedge-sys/aot"]
-async = ["wasmedge-sys/async"]
+async = ["wasmedge-sys/async", "dep:async-wasi"]
 default = []
 ffi = ["wasmedge-sys/ffi"]
 standalone = ["wasmedge-sys/standalone"]
diff --git a/crates/async-wasi/Cargo.toml b/crates/async-wasi/Cargo.toml
index d3822701c..e9059698c 100644
--- a/crates/async-wasi/Cargo.toml
+++ b/crates/async-wasi/Cargo.toml
@@ -7,7 +7,7 @@ license = "Apache-2.0"
 name = "async-wasi"
 readme = "README.md"
 repository = "https://github.com/WasmEdge/wasmedge-rust-sdk"
-version = "0.0.2"
+version = "0.0.3"
 
 [dependencies]
 bitflags = "2.0.2"
@@ -19,6 +19,7 @@ path-absolutize = "3.0.13"
 serde = {version = "1", features = ["derive"], optional = true}
 socket2 = {version = "^0.4.9", features = ["all"]}
 tokio = {version = "1", features = ["full"], optional = true}
+parking_lot.workspace = true
 
 [dev-dependencies]
 serde_json = {version = "1"}
diff --git a/crates/async-wasi/src/lib.rs b/crates/async-wasi/src/lib.rs
index c24dda66d..619f3fd57 100644
--- a/crates/async-wasi/src/lib.rs
+++ b/crates/async-wasi/src/lib.rs
@@ -13,3 +13,5 @@
 pub mod object_pool;
 #[allow(clippy::too_many_arguments)]
 pub mod snapshots;
+
+pub use snapshots::WasiCtx;
diff --git a/crates/async-wasi/src/snapshots/mod.rs b/crates/async-wasi/src/snapshots/mod.rs
index 308bcc3fc..221e78e94 100644
--- a/crates/async-wasi/src/snapshots/mod.rs
+++ b/crates/async-wasi/src/snapshots/mod.rs
@@ -7,11 +7,14 @@ use common::error::Errno;
 use env::{wasi_types::__wasi_fd_t, VFD};
 use std::path::PathBuf;
 
-#[derive(Debug)]
+use parking_lot::RwLock;
+use std::sync::Arc;
+
+#[derive(Debug, Clone)]
 pub struct WasiCtx {
-    args: Vec<String>,
+    pub args: Vec<String>,
     envs: Vec<String>,
-    vfs: ObjectPool<VFD>,
+    vfs: Arc<RwLock<ObjectPool<VFD>>>,
     closed: Option<__wasi_fd_t>,
     vfs_preopen_limit: usize,
     #[cfg(feature = "serialize")]
@@ -36,7 +39,7 @@ impl WasiCtx {
         WasiCtx {
             args: vec![],
             envs: vec![],
-            vfs,
+            vfs: Arc::new(RwLock::new(vfs)),
             vfs_preopen_limit: 2,
             closed: None,
             #[cfg(feature = "serialize")]
@@ -48,6 +51,7 @@ impl WasiCtx {
     pub fn push_preopen(&mut self, host_path: PathBuf, guest_path: PathBuf) {
         let preopen = env::vfs::WasiPreOpenDir::new(host_path, guest_path);
         self.vfs
+            .write()
             .push(VFD::Inode(env::vfs::INode::PreOpenDir(preopen)));
         self.vfs_preopen_limit += 1;
     }
@@ -80,10 +84,12 @@ impl WasiCtx {
             Err(Errno::__WASI_ERRNO_BADF)
         } else {
             self.remove_closed();
-            let vfd = self
-                .vfs
-                .get_mut(fd as usize)
-                .ok_or(Errno::__WASI_ERRNO_BADF)?;
+
+            let vfd = unsafe {
+                (*self.vfs.data_ptr())
+                    .get_mut(fd as usize)
+                    .ok_or(Errno::__WASI_ERRNO_BADF)?
+            };
             if let VFD::Closed = vfd {
                 let _ = self.closed.insert(fd);
                 return Err(Errno::__WASI_ERRNO_BADF);
@@ -96,7 +102,11 @@ impl WasiCtx {
         if fd < 0 {
             Err(Errno::__WASI_ERRNO_BADF)
         } else {
-            let vfd = self.vfs.get(fd as usize).ok_or(Errno::__WASI_ERRNO_BADF)?;
+            let vfd = unsafe {
+                (*self.vfs.data_ptr())
+                    .get(fd as usize)
+                    .ok_or(Errno::__WASI_ERRNO_BADF)?
+            };
             if let VFD::Closed = vfd {
                 return Err(Errno::__WASI_ERRNO_BADF);
             }
@@ -105,7 +115,7 @@ impl WasiCtx {
     }
 
     pub fn insert_vfd(&mut self, vfd: VFD) -> Result<__wasi_fd_t, Errno> {
-        let i = self.vfs.push(vfd);
+        let i = self.vfs.write().push(vfd);
 
         Ok(i.0 as __wasi_fd_t)
     }
@@ -115,7 +125,7 @@ impl WasiCtx {
             return Err(Errno::__WASI_ERRNO_NOTSUP);
         }
 
-        self.vfs.remove(fd as usize);
+        self.vfs.write().remove(fd as usize);
 
         Ok(())
     }
@@ -132,11 +142,16 @@ impl WasiCtx {
             return Err(Errno::__WASI_ERRNO_NOTSUP);
         };
 
-        let _ = self.vfs.get(to).ok_or(Errno::__WASI_ERRNO_BADF)?;
+        let _ = self.vfs.read().get(to).ok_or(Errno::__WASI_ERRNO_BADF)?;
 
-        let from_entry = self.vfs.remove(from).ok_or(Errno::__WASI_ERRNO_BADF)?;
+        let from_entry = self
+            .vfs
+            .write()
+            .remove(from)
+            .ok_or(Errno::__WASI_ERRNO_BADF)?;
 
-        let to_entry = self.vfs.get_mut(to).ok_or(Errno::__WASI_ERRNO_BADF)?;
+        let mut vfs = self.vfs.write();
+        let to_entry = vfs.get_mut(to).ok_or(Errno::__WASI_ERRNO_BADF)?;
 
         *to_entry = from_entry;
 
@@ -222,6 +237,7 @@ mod vfs_test {
 
         let v = ctx
             .vfs
+            .read()
             .iter()
             .take(7)
             .map(|f| f.is_some())
@@ -245,8 +261,9 @@ pub mod serialize {
         VFD,
     };
     use crate::object_pool::SerialObjectPool;
+    use parking_lot::RwLock;
     use serde::{Deserialize, Serialize};
-    use std::{net::SocketAddr, path::PathBuf, time::SystemTime};
+    use std::{net::SocketAddr, path::PathBuf, sync::Arc, time::SystemTime};
 
     #[derive(Debug, Clone, Deserialize, Serialize)]
     pub enum PollFdState {
@@ -303,7 +320,7 @@ pub mod serialize {
 
     impl From<&super::WasiCtx> for SerialWasiCtx {
         fn from(ctx: &super::WasiCtx) -> Self {
-            let vfs = SerialObjectPool::from_ref(&ctx.vfs, |fd| SerialVFD::from(fd));
+            let vfs = SerialObjectPool::from_ref(&ctx.vfs.read(), |fd| SerialVFD::from(fd));
             Self {
                 args: ctx.args.clone(),
                 envs: ctx.envs.clone(),
@@ -331,7 +348,7 @@ pub mod serialize {
             super::WasiCtx {
                 args,
                 envs,
-                vfs,
+                vfs: Arc::new(RwLock::new(vfs)),
                 vfs_preopen_limit,
                 closed: None,
                 io_state,
diff --git a/crates/wasmedge-sys/Cargo.toml b/crates/wasmedge-sys/Cargo.toml
index 6ce0dd02a..da2bf7351 100644
--- a/crates/wasmedge-sys/Cargo.toml
+++ b/crates/wasmedge-sys/Cargo.toml
@@ -10,7 +10,7 @@ links = "wasmedge"
 name = "wasmedge-sys"
 readme = "README.md"
 repository = "https://github.com/WasmEdge/wasmedge-rust-sdk"
-version = "0.15.1"
+version = "0.16.0"
 
 [dependencies]
 fiber-for-wasmedge = {version = "8.0.1", optional = true}
@@ -18,15 +18,16 @@ libc = "0.2.94"
 paste = "1.0.5"
 scoped-tls = "1"
 thiserror = "1.0.30"
-wasmedge-macro = {path = "../wasmedge-macro", version = "0.5"}
-wasmedge-types = {path = "../wasmedge-types", version = "0.4"}
+wasmedge-macro.workspace = true
+wasmedge-types.workspace = true
 wat.workspace = true
 lazy_static = "1.4.0"
-parking_lot = "0.12.1"
+parking_lot.workspace = true
 rand = "0.8.4"
+cfg-if.workspace = true
 
 [target.'cfg(target_os = "linux")'.dependencies]
-async-wasi = {path = "../async-wasi", version = "0.0.2", optional = true}
+async-wasi = {workspace = true, optional = true}
 
 [build-dependencies]
 bindgen = {version = "0.65", default-features = false, features = ["runtime"]}
diff --git a/crates/wasmedge-sys/src/async.rs b/crates/wasmedge-sys/src/async/fiber.rs
similarity index 100%
rename from crates/wasmedge-sys/src/async.rs
rename to crates/wasmedge-sys/src/async/fiber.rs
diff --git a/crates/wasmedge-sys/src/async/function.rs b/crates/wasmedge-sys/src/async/function.rs
new file mode 100644
index 000000000..d5871e6f0
--- /dev/null
+++ b/crates/wasmedge-sys/src/async/function.rs
@@ -0,0 +1,232 @@
+use crate::{
+    ffi, instance::function::InnerFunc, r#async::fiber::AsyncCx, CallingFrame, FuncType,
+    WasmEdgeResult, WasmValue,
+};
+use parking_lot::Mutex;
+use std::{pin::Pin, sync::Arc};
+use wasmedge_types::{
+    error::{FuncError, HostFuncError, WasmEdgeError},
+    NeverType,
+};
+
+/// Defines a host function.
+///
+/// A WasmEdge [Function] defines a WebAssembly host function described by its [type](crate::FuncType). A host function is a closure of the original function defined in either the host or the WebAssembly module.
+#[derive(Debug)]
+pub(crate) struct WasiFunction {
+    pub(crate) inner: Arc<Mutex<InnerFunc>>,
+    pub(crate) registered: bool,
+}
+impl WasiFunction {
+    pub(crate) fn create_wasi_func<T>(
+        ty: &FuncType,
+        real_fn: HostFn<T>,
+        ctx_data: Option<&mut T>,
+        cost: u64,
+    ) -> WasmEdgeResult<Self> {
+        let data = match ctx_data {
+            Some(d) => d as *mut T as *mut std::os::raw::c_void,
+            None => std::ptr::null_mut(),
+        };
+
+        let ctx = unsafe {
+            ffi::WasmEdge_FunctionInstanceCreateBinding(
+                ty.inner.0,
+                Some(wrap_sync_wasi_fn::<T>),
+                real_fn as *mut _,
+                data,
+                cost,
+            )
+        };
+
+        match ctx.is_null() {
+            true => Err(Box::new(WasmEdgeError::Func(FuncError::Create))),
+            false => Ok(Self {
+                inner: Arc::new(Mutex::new(InnerFunc(ctx))),
+                registered: false,
+            }),
+        }
+    }
+
+    pub(crate) fn create_async_wasi_func<T>(
+        ty: &FuncType,
+        real_fn: AsyncHostFn<T>,
+        ctx_data: Option<&mut T>,
+        cost: u64,
+    ) -> WasmEdgeResult<Self> {
+        let data = match ctx_data {
+            Some(d) => d as *mut T as *mut std::os::raw::c_void,
+            None => std::ptr::null_mut(),
+        };
+
+        let ctx = unsafe {
+            ffi::WasmEdge_FunctionInstanceCreateBinding(
+                ty.inner.0,
+                Some(wrap_async_wasi_fn::<T>),
+                real_fn as *mut _,
+                data,
+                cost,
+            )
+        };
+
+        match ctx.is_null() {
+            true => Err(Box::new(WasmEdgeError::Func(FuncError::Create))),
+            false => Ok(Self {
+                inner: Arc::new(Mutex::new(InnerFunc(ctx))),
+                registered: false,
+            }),
+        }
+    }
+}
+impl Clone for WasiFunction {
+    fn clone(&self) -> Self {
+        Self {
+            inner: self.inner.clone(),
+            registered: self.registered,
+        }
+    }
+}
+
+/// Defines the signature of an asynchronous host function.
+pub(crate) type AsyncHostFn<T> =
+    fn(
+        CallingFrame,
+        Vec<WasmValue>,
+        Option<&'static mut T>,
+    ) -> Box<dyn std::future::Future<Output = Result<Vec<WasmValue>, HostFuncError>> + Send>;
+
+/// Defines the signature of a host function.
+pub(crate) type HostFn<T> = fn(
+    CallingFrame,
+    Vec<WasmValue>,
+    Option<&'static mut T>,
+) -> Result<Vec<WasmValue>, HostFuncError>;
+
+extern "C" fn wrap_sync_wasi_fn<T: 'static>(
+    key_ptr: *mut std::ffi::c_void,
+    data: *mut std::ffi::c_void,
+    call_frame_ctx: *const ffi::WasmEdge_CallingFrameContext,
+    params: *const ffi::WasmEdge_Value,
+    param_len: u32,
+    returns: *mut ffi::WasmEdge_Value,
+    return_len: u32,
+) -> ffi::WasmEdge_Result {
+    let frame = CallingFrame::create(call_frame_ctx);
+
+    // recover the async host function
+    let real_func: HostFn<T> = unsafe { std::mem::transmute(key_ptr) };
+
+    // recover the context data
+    let data = if std::any::TypeId::of::<T>() == std::any::TypeId::of::<NeverType>() {
+        None
+    } else {
+        let data: &'static mut T = unsafe { &mut *(data as *mut T) };
+        Some(data)
+    };
+
+    // input arguments
+    let input = {
+        let raw_input = unsafe {
+            std::slice::from_raw_parts(
+                params,
+                param_len
+                    .try_into()
+                    .expect("len of params should not greater than usize"),
+            )
+        };
+        raw_input.iter().map(|r| (*r).into()).collect::<Vec<_>>()
+    };
+
+    // returns
+    let return_len = return_len
+        .try_into()
+        .expect("len of returns should not greater than usize");
+    let raw_returns = unsafe { std::slice::from_raw_parts_mut(returns, return_len) };
+
+    match real_func(frame, input, data) {
+        Ok(returns) => {
+            assert!(returns.len() == return_len, "[wasmedge-sys] check the number of returns of host function. Expected: {}, actual: {}", return_len, returns.len());
+            for (idx, wasm_value) in returns.into_iter().enumerate() {
+                raw_returns[idx] = wasm_value.as_raw();
+            }
+            ffi::WasmEdge_Result { Code: 0 }
+        }
+        Err(err) => match err {
+            HostFuncError::User(code) => unsafe {
+                ffi::WasmEdge_ResultGen(ffi::WasmEdge_ErrCategory_UserLevelError, code)
+            },
+            HostFuncError::Runtime(code) => unsafe {
+                ffi::WasmEdge_ResultGen(ffi::WasmEdge_ErrCategory_WASM, code)
+            },
+        },
+    }
+}
+
+extern "C" fn wrap_async_wasi_fn<T: 'static>(
+    key_ptr: *mut std::ffi::c_void,
+    data: *mut std::ffi::c_void,
+    call_frame_ctx: *const ffi::WasmEdge_CallingFrameContext,
+    params: *const ffi::WasmEdge_Value,
+    param_len: u32,
+    returns: *mut ffi::WasmEdge_Value,
+    return_len: u32,
+) -> ffi::WasmEdge_Result {
+    let frame = CallingFrame::create(call_frame_ctx);
+
+    // recover the async host function
+    let real_func: AsyncHostFn<T> = unsafe { std::mem::transmute(key_ptr) };
+
+    // recover the context data
+    let data = if std::any::TypeId::of::<T>() == std::any::TypeId::of::<NeverType>() {
+        None
+    } else {
+        let data: &'static mut T = unsafe { &mut *(data as *mut T) };
+        Some(data)
+    };
+
+    // arguments
+    let input = {
+        let raw_input = unsafe {
+            std::slice::from_raw_parts(
+                params,
+                param_len
+                    .try_into()
+                    .expect("len of params should not greater than usize"),
+            )
+        };
+        raw_input.iter().map(|r| (*r).into()).collect::<Vec<_>>()
+    };
+
+    // returns
+    let return_len = return_len
+        .try_into()
+        .expect("len of returns should not greater than usize");
+    let raw_returns = unsafe { std::slice::from_raw_parts_mut(returns, return_len) };
+
+    let async_cx = AsyncCx::new();
+    let mut future = Pin::from(real_func(frame, input, data));
+    let result = match unsafe { async_cx.block_on(future.as_mut()) } {
+        Ok(Ok(ret)) => Ok(ret),
+        Ok(Err(err)) => Err(err),
+        Err(_err) => Err(HostFuncError::User(0x87)),
+    };
+
+    // parse result
+    match result {
+        Ok(returns) => {
+            assert!(returns.len() == return_len, "[wasmedge-sys] check the number of returns of async host function. Expected: {}, actual: {}", return_len, returns.len());
+            for (idx, wasm_value) in returns.into_iter().enumerate() {
+                raw_returns[idx] = wasm_value.as_raw();
+            }
+            ffi::WasmEdge_Result { Code: 0 }
+        }
+        Err(err) => match err {
+            HostFuncError::User(code) => unsafe {
+                ffi::WasmEdge_ResultGen(ffi::WasmEdge_ErrCategory_UserLevelError, code)
+            },
+            HostFuncError::Runtime(code) => unsafe {
+                ffi::WasmEdge_ResultGen(ffi::WasmEdge_ErrCategory_WASM, code)
+            },
+        },
+    }
+}
diff --git a/crates/wasmedge-sys/src/async/mod.rs b/crates/wasmedge-sys/src/async/mod.rs
new file mode 100644
index 000000000..ce5973c2f
--- /dev/null
+++ b/crates/wasmedge-sys/src/async/mod.rs
@@ -0,0 +1,5 @@
+pub mod fiber;
+pub(crate) mod function;
+pub mod module;
+
+pub use module::AsyncWasiModule;
diff --git a/crates/wasmedge-sys/src/async_wasi.rs b/crates/wasmedge-sys/src/async/module.rs
similarity index 86%
rename from crates/wasmedge-sys/src/async_wasi.rs
rename to crates/wasmedge-sys/src/async/module.rs
index bf2c8a358..8760d7111 100644
--- a/crates/wasmedge-sys/src/async_wasi.rs
+++ b/crates/wasmedge-sys/src/async/module.rs
@@ -1,9 +1,9 @@
+use super::function::{AsyncHostFn, HostFn, WasiFunction};
 use crate::{
-    instance::function::{AsyncHostFn, HostFn},
-    CallingFrame, Memory, WasmValue,
+    ffi, instance::module::InnerInstance, types::WasmEdgeString, CallingFrame, Memory,
+    WasmEdgeResult, WasmValue,
 };
-use async_wasi as wasi;
-use wasi::snapshots::{
+use async_wasi::snapshots::{
     common::{
         error::Errno,
         memory::WasmPtr,
@@ -11,100 +11,206 @@ use wasi::snapshots::{
     },
     preview_1 as p, WasiCtx,
 };
+use parking_lot::Mutex;
+use std::{path::PathBuf, sync::Arc};
 use wasmedge_macro::{sys_async_wasi_host_function, sys_wasi_host_function};
-use wasmedge_types::{error::HostFuncError, ValType};
+use wasmedge_types::{
+    error::{HostFuncError, InstanceError, WasmEdgeError},
+    ValType,
+};
 
-fn to_wasm_return(r: Result<(), Errno>) -> Vec<WasmValue> {
-    let code = if let Err(e) = r { e.0 } else { 0 };
-    vec![WasmValue::from_i32(code as i32)]
+/// A [AsyncWasiModule] is a module instance for the WASI specification and used in the `async` scenario.
+#[derive(Debug, Clone)]
+pub struct AsyncWasiModule {
+    pub(crate) inner: Arc<InnerInstance>,
+    pub(crate) registered: bool,
+    name: String,
+    wasi_ctx: Arc<Mutex<WasiCtx>>,
 }
-
-impl async_wasi::snapshots::common::memory::Memory for Memory {
-    fn get_data<T: Sized>(&self, offset: WasmPtr<T>) -> Result<&T, Errno> {
-        unsafe {
-            let r = std::mem::size_of::<T>();
-            let ptr = self
-                .data_pointer(offset.0 as u32, r as u32)
-                .map_err(|_| Errno::__WASI_ERRNO_FAULT)?;
-            Ok(ptr.cast::<T>().as_ref().unwrap())
+impl Drop for AsyncWasiModule {
+    fn drop(&mut self) {
+        if !self.registered && Arc::strong_count(&self.inner) == 1 && !self.inner.0.is_null() {
+            // free the module instance
+            unsafe {
+                ffi::WasmEdge_ModuleInstanceDelete(self.inner.0);
+            }
         }
     }
+}
+impl AsyncWasiModule {
+    /// Creates a [AsyncWasiModule] instance.
+    ///
+    /// # Arguments
+    ///
+    /// * `args` - The commandline arguments. The first argument is the program name.
+    ///
+    /// * `envs` - The environment variables.
+    ///
+    /// * `preopens` - The directories to pre-open.
+    ///
+    /// # Error
+    ///
+    /// If fail to create a [AsyncWasiModule] instance, then an error is returned.
+    pub fn create(
+        args: Option<Vec<&str>>,
+        envs: Option<Vec<(&str, &str)>>,
+        preopens: Option<Vec<(PathBuf, PathBuf)>>,
+    ) -> WasmEdgeResult<Self> {
+        // create wasi context
+        let mut wasi_ctx = WasiCtx::new();
+
+        // push args, envs and preopens
+        if let Some(args) = args {
+            wasi_ctx.push_args(args.iter().map(|x| x.to_string()).collect());
+        }
+        if let Some(envs) = envs {
+            wasi_ctx.push_envs(envs.iter().map(|(k, v)| format!("{}={}", k, v)).collect());
+        }
+        if let Some(preopens) = preopens {
+            for (host_dir, guest_dir) in preopens {
+                wasi_ctx.push_preopen(host_dir, guest_dir)
+            }
+        }
 
-    fn get_slice<T: Sized>(&self, offset: WasmPtr<T>, len: usize) -> Result<&[T], Errno> {
-        unsafe {
-            let r = std::mem::size_of::<T>() * len;
-            let ptr = self
-                .data_pointer(offset.0 as u32, r as u32)
-                .map_err(|_| Errno::__WASI_ERRNO_FAULT)? as *const T;
-            Ok(std::slice::from_raw_parts(ptr, len))
+        // create wasi module
+        let name = "wasi_snapshot_preview1";
+        let raw_name = WasmEdgeString::from(name);
+        let ctx = unsafe { ffi::WasmEdge_ModuleInstanceCreate(raw_name.as_raw()) };
+        if ctx.is_null() {
+            return Err(Box::new(WasmEdgeError::Instance(
+                InstanceError::CreateImportModule,
+            )));
         }
-    }
+        let mut async_wasi_module = Self {
+            inner: std::sync::Arc::new(InnerInstance(ctx)),
+            registered: false,
+            name: name.to_string(),
+            wasi_ctx: Arc::new(Mutex::new(wasi_ctx)),
+        };
 
-    fn get_iovec<'a>(
-        &self,
-        iovec_ptr: WasmPtr<__wasi_ciovec_t>,
-        iovec_len: __wasi_size_t,
-    ) -> Result<Vec<std::io::IoSlice<'a>>, Errno> {
-        unsafe {
-            let iovec = self.get_slice(iovec_ptr, iovec_len as usize)?.to_vec();
-            let mut result = Vec::with_capacity(iovec.len());
-            for i in iovec {
-                let ptr = self
-                    .data_pointer(i.buf, i.buf_len)
-                    .map_err(|_| Errno::__WASI_ERRNO_FAULT)?;
-                let s = std::io::IoSlice::new(std::slice::from_raw_parts(ptr, i.buf_len as usize));
-                result.push(s);
+        // add sync/async host functions to the module
+        for wasi_func in wasi_impls() {
+            match wasi_func {
+                WasiFunc::SyncFn(name, (ty_args, ty_rets), real_fn) => {
+                    let func_ty = crate::FuncType::create(ty_args, ty_rets)?;
+
+                    let func = WasiFunction::create_wasi_func(
+                        &func_ty,
+                        real_fn,
+                        Some(&mut async_wasi_module.wasi_ctx.lock()),
+                        0,
+                    )?;
+
+                    async_wasi_module.add_wasi_func(&name, func);
+                }
+                WasiFunc::AsyncFn(name, (ty_args, ty_rets), real_async_fn) => {
+                    let func_ty = crate::FuncType::create(ty_args, ty_rets)?;
+
+                    let func = WasiFunction::create_async_wasi_func(
+                        &func_ty,
+                        real_async_fn,
+                        Some(&mut async_wasi_module.wasi_ctx.lock()),
+                        0,
+                    )?;
+
+                    async_wasi_module.add_wasi_func(&name, func);
+                }
             }
-            Ok(result)
         }
+
+        Ok(async_wasi_module)
     }
 
-    fn mut_data<T: Sized>(&mut self, offset: WasmPtr<T>) -> Result<&mut T, Errno> {
-        unsafe {
-            let r = std::mem::size_of::<T>();
-            let ptr = self
-                .data_pointer_mut(offset.0 as u32, r as u32)
-                .map_err(|_| Errno::__WASI_ERRNO_FAULT)?;
-            Ok(ptr.cast::<T>().as_mut().unwrap())
+    /// Creates a [AsyncWasiModule] instance with the given wasi context.
+    ///
+    /// # Arguments
+    ///
+    /// * `wasi_ctx` - The [WasiCtx](async_wasi::snapshots::WasiCtx) instance.
+    ///
+    /// # Error
+    ///
+    /// If fail to create [AsyncWasiModule] instance, then an error is returned.
+    pub fn create_from_wasi_context(wasi_ctx: WasiCtx) -> WasmEdgeResult<Self> {
+        // create wasi module
+        let name = "wasi_snapshot_preview1";
+        let raw_name = WasmEdgeString::from(name);
+        let ctx = unsafe { ffi::WasmEdge_ModuleInstanceCreate(raw_name.as_raw()) };
+        if ctx.is_null() {
+            return Err(Box::new(WasmEdgeError::Instance(
+                InstanceError::CreateImportModule,
+            )));
         }
-    }
+        let mut async_wasi_module = Self {
+            inner: std::sync::Arc::new(InnerInstance(ctx)),
+            registered: false,
+            name: name.to_string(),
+            wasi_ctx: Arc::new(Mutex::new(wasi_ctx)),
+        };
 
-    fn mut_slice<T: Sized>(&mut self, offset: WasmPtr<T>, len: usize) -> Result<&mut [T], Errno> {
-        unsafe {
-            let r = std::mem::size_of::<T>() * len;
-            let ptr = self
-                .data_pointer_mut(offset.0 as u32, r as u32)
-                .map_err(|_| Errno::__WASI_ERRNO_FAULT)? as *mut T;
-            Ok(std::slice::from_raw_parts_mut(ptr, len))
+        // add sync/async host functions to the module
+        for wasi_func in wasi_impls() {
+            match wasi_func {
+                WasiFunc::SyncFn(name, (ty_args, ty_rets), real_fn) => {
+                    let func_ty = crate::FuncType::create(ty_args, ty_rets)?;
+
+                    let func = WasiFunction::create_wasi_func(
+                        &func_ty,
+                        real_fn,
+                        Some(&mut async_wasi_module.wasi_ctx.lock()),
+                        0,
+                    )?;
+
+                    async_wasi_module.add_wasi_func(&name, func);
+                }
+                WasiFunc::AsyncFn(name, (ty_args, ty_rets), real_async_fn) => {
+                    let func_ty = crate::FuncType::create(ty_args, ty_rets)?;
+
+                    let func = WasiFunction::create_async_wasi_func(
+                        &func_ty,
+                        real_async_fn,
+                        Some(&mut async_wasi_module.wasi_ctx.lock()),
+                        0,
+                    )?;
+
+                    async_wasi_module.add_wasi_func(&name, func);
+                }
+            }
         }
+
+        Ok(async_wasi_module)
     }
 
-    fn mut_iovec(
-        &mut self,
-        iovec_ptr: WasmPtr<async_wasi::snapshots::env::wasi_types::__wasi_iovec_t>,
-        iovec_len: async_wasi::snapshots::env::wasi_types::__wasi_size_t,
-    ) -> Result<Vec<std::io::IoSliceMut<'_>>, Errno> {
+    /// Returns the name of the module instance.
+    pub fn name(&self) -> &str {
+        self.name.as_str()
+    }
+
+    /// Imports a [WasiFunction](crate::r#async::function::WasiFunction) instance.
+    ///
+    /// # Arguments
+    ///
+    /// * `name` - The name of the host function instance to import.
+    ///
+    /// * `func` - The [WasiFunction](crate::r#async::function::WasiFunction) instance to import.
+    fn add_wasi_func(&mut self, name: impl AsRef<str>, func: WasiFunction) {
+        let func_name: WasmEdgeString = name.into();
+
         unsafe {
-            let iovec = self.get_slice(iovec_ptr, iovec_len as usize)?.to_vec();
-            let mut result = Vec::with_capacity(iovec.len());
-            for i in iovec {
-                let ptr = self
-                    .data_pointer_mut(i.buf, i.buf_len)
-                    .map_err(|_| Errno::__WASI_ERRNO_FAULT)?;
-                let s = std::io::IoSliceMut::new(std::slice::from_raw_parts_mut(
-                    ptr,
-                    i.buf_len as usize,
-                ));
-                result.push(s);
-            }
-            Ok(result)
+            ffi::WasmEdge_ModuleInstanceAddFunction(
+                self.inner.0,
+                func_name.as_raw(),
+                func.inner.lock().0,
+            );
         }
+
+        func.inner.lock().0 = std::ptr::null_mut();
     }
 
-    fn write_data<T: Sized>(&mut self, offset: WasmPtr<T>, data: T) -> Result<(), Errno> {
-        let p = self.mut_data(offset)?;
-        *p = data;
-        Ok(())
+    /// Returns the WASI exit code.
+    ///
+    /// The WASI exit code can be accessed after running the "_start" function of a `wasm32-wasi` program.
+    pub fn exit_code(&self) -> u32 {
+        self.wasi_ctx.lock().exit_code
     }
 }
 
@@ -2136,3 +2242,162 @@ pub fn wasi_impls() -> Vec<WasiFunc<WasiCtx>> {
         ),
     ]
 }
+
+fn to_wasm_return(r: Result<(), Errno>) -> Vec<WasmValue> {
+    let code = if let Err(e) = r { e.0 } else { 0 };
+    vec![WasmValue::from_i32(code as i32)]
+}
+
+impl async_wasi::snapshots::common::memory::Memory for Memory {
+    fn get_data<T: Sized>(&self, offset: WasmPtr<T>) -> Result<&T, Errno> {
+        unsafe {
+            let r = std::mem::size_of::<T>();
+            let ptr = self
+                .data_pointer(offset.0 as u32, r as u32)
+                .map_err(|_| Errno::__WASI_ERRNO_FAULT)?;
+            Ok(ptr.cast::<T>().as_ref().unwrap())
+        }
+    }
+
+    fn get_slice<T: Sized>(&self, offset: WasmPtr<T>, len: usize) -> Result<&[T], Errno> {
+        unsafe {
+            let r = std::mem::size_of::<T>() * len;
+            let ptr = self
+                .data_pointer(offset.0 as u32, r as u32)
+                .map_err(|_| Errno::__WASI_ERRNO_FAULT)? as *const T;
+            Ok(std::slice::from_raw_parts(ptr, len))
+        }
+    }
+
+    fn get_iovec<'a>(
+        &self,
+        iovec_ptr: WasmPtr<__wasi_ciovec_t>,
+        iovec_len: __wasi_size_t,
+    ) -> Result<Vec<std::io::IoSlice<'a>>, Errno> {
+        unsafe {
+            let iovec = self.get_slice(iovec_ptr, iovec_len as usize)?.to_vec();
+            let mut result = Vec::with_capacity(iovec.len());
+            for i in iovec {
+                let ptr = self
+                    .data_pointer(i.buf, i.buf_len)
+                    .map_err(|_| Errno::__WASI_ERRNO_FAULT)?;
+                let s = std::io::IoSlice::new(std::slice::from_raw_parts(ptr, i.buf_len as usize));
+                result.push(s);
+            }
+            Ok(result)
+        }
+    }
+
+    fn mut_data<T: Sized>(&mut self, offset: WasmPtr<T>) -> Result<&mut T, Errno> {
+        unsafe {
+            let r = std::mem::size_of::<T>();
+            let ptr = self
+                .data_pointer_mut(offset.0 as u32, r as u32)
+                .map_err(|_| Errno::__WASI_ERRNO_FAULT)?;
+            Ok(ptr.cast::<T>().as_mut().unwrap())
+        }
+    }
+
+    fn mut_slice<T: Sized>(&mut self, offset: WasmPtr<T>, len: usize) -> Result<&mut [T], Errno> {
+        unsafe {
+            let r = std::mem::size_of::<T>() * len;
+            let ptr = self
+                .data_pointer_mut(offset.0 as u32, r as u32)
+                .map_err(|_| Errno::__WASI_ERRNO_FAULT)? as *mut T;
+            Ok(std::slice::from_raw_parts_mut(ptr, len))
+        }
+    }
+
+    fn mut_iovec(
+        &mut self,
+        iovec_ptr: WasmPtr<async_wasi::snapshots::env::wasi_types::__wasi_iovec_t>,
+        iovec_len: async_wasi::snapshots::env::wasi_types::__wasi_size_t,
+    ) -> Result<Vec<std::io::IoSliceMut<'_>>, Errno> {
+        unsafe {
+            let iovec = self.get_slice(iovec_ptr, iovec_len as usize)?.to_vec();
+            let mut result = Vec::with_capacity(iovec.len());
+            for i in iovec {
+                let ptr = self
+                    .data_pointer_mut(i.buf, i.buf_len)
+                    .map_err(|_| Errno::__WASI_ERRNO_FAULT)?;
+                let s = std::io::IoSliceMut::new(std::slice::from_raw_parts_mut(
+                    ptr,
+                    i.buf_len as usize,
+                ));
+                result.push(s);
+            }
+            Ok(result)
+        }
+    }
+
+    fn write_data<T: Sized>(&mut self, offset: WasmPtr<T>, data: T) -> Result<(), Errno> {
+        let p = self.mut_data(offset)?;
+        *p = data;
+        Ok(())
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::{
+        r#async::fiber::AsyncState, Config, Executor, ImportObject, Loader, Store, Validator,
+    };
+
+    #[tokio::test]
+    async fn test_async_wasi_module() -> Result<(), Box<dyn std::error::Error>> {
+        // create a Config
+        let mut config = Config::create()?;
+        config.wasi(true);
+        assert!(config.wasi_enabled());
+
+        // create an Executor
+        let result = Executor::create(None, None);
+        assert!(result.is_ok());
+        let mut executor = result.unwrap();
+        assert!(!executor.inner.0.is_null());
+
+        // create a Store
+        let result = Store::create();
+        assert!(result.is_ok());
+        let mut store = result.unwrap();
+
+        // create an AsyncWasiModule
+        let result = AsyncWasiModule::create(Some(vec!["abc"]), Some(vec![("ENV", "1")]), None);
+        assert!(result.is_ok());
+        let async_wasi_module = result.unwrap();
+
+        // register async_wasi module into the store
+        let wasi_import = ImportObject::AsyncWasi(async_wasi_module);
+        let result = executor.register_import_object(&mut store, &wasi_import);
+        assert!(result.is_ok());
+
+        let wasm_file = std::env::current_dir()
+            .unwrap()
+            .ancestors()
+            .nth(2)
+            .unwrap()
+            .join("examples/wasmedge-sys/async_hello.wasm");
+        let module = Loader::create(None)?.from_file(&wasm_file)?;
+        Validator::create(None)?.validate(&module)?;
+        let instance = executor.register_active_module(&mut store, &module)?;
+        let fn_start = instance.get_func("_start")?;
+
+        async fn tick() {
+            let mut i = 0;
+            loop {
+                println!("[tick] i={i}");
+                tokio::time::sleep(std::time::Duration::from_millis(500)).await;
+                i += 1;
+            }
+        }
+        tokio::spawn(tick());
+
+        let async_state = AsyncState::new();
+        let _ = executor
+            .call_func_async(&async_state, &fn_start, [])
+            .await?;
+
+        Ok(())
+    }
+}
diff --git a/crates/wasmedge-sys/src/executor.rs b/crates/wasmedge-sys/src/executor.rs
index 05d6878c9..b38989006 100644
--- a/crates/wasmedge-sys/src/executor.rs
+++ b/crates/wasmedge-sys/src/executor.rs
@@ -2,7 +2,7 @@
 
 use super::ffi;
 #[cfg(all(feature = "async", target_os = "linux"))]
-use crate::r#async::{AsyncState, FiberFuture};
+use crate::r#async::fiber::{AsyncState, FiberFuture};
 use crate::{
     instance::module::InnerInstance, types::WasmEdgeString, utils::check, Config, Engine, FuncRef,
     Function, ImportObject, Instance, Module, Statistics, Store, WasmEdgeResult, WasmValue,
@@ -365,8 +365,13 @@ unsafe impl Sync for InnerExecutor {}
 #[cfg(test)]
 mod tests {
     use super::*;
-    #[cfg(all(feature = "async", target_os = "linux"))]
-    use crate::{instance::module::AsyncWasiModule, Loader, Validator};
+    cfg_if::cfg_if! {
+        if #[cfg(all(feature = "async", target_os = "linux"))] {
+            use crate::r#async::AsyncWasiModule;
+            use crate::{Loader, Validator};
+            use wasmedge_macro::sys_async_host_function;
+        }
+    }
     use crate::{
         AsImport, CallingFrame, Config, FuncType, Function, Global, GlobalType, ImportModule,
         MemType, Memory, Statistics, Table, TableType, HOST_FUNCS, HOST_FUNC_FOOTPRINTS,
@@ -375,8 +380,6 @@ mod tests {
         sync::{Arc, Mutex},
         thread,
     };
-    #[cfg(all(feature = "async", target_os = "linux"))]
-    use wasmedge_macro::sys_async_host_function;
     use wasmedge_macro::sys_host_function;
     use wasmedge_types::{error::HostFuncError, Mutability, NeverType, RefType, ValType};
 
@@ -596,15 +599,15 @@ mod tests {
         let mut store = result.unwrap();
 
         // create an AsyncWasiModule
-        let result = AsyncWasiModule::create(Some(vec!["abc"]), Some(vec![("a", "1")]), None);
+        let result = AsyncWasiModule::create(Some(vec!["abc"]), Some(vec![("ENV", "1")]), None);
         assert!(result.is_ok());
         let async_wasi_module = result.unwrap();
 
-        // register async_wasi module into the store
         let wasi_import = ImportObject::AsyncWasi(async_wasi_module);
         let result = executor.register_import_object(&mut store, &wasi_import);
         assert!(result.is_ok());
 
+        // register async_wasi module into the store
         let wasm_file = std::env::current_dir()
             .unwrap()
             .ancestors()
@@ -676,7 +679,7 @@ mod tests {
         let mut store = result.unwrap();
 
         // create an AsyncWasiModule
-        let result = AsyncWasiModule::create(Some(vec!["abc"]), Some(vec![("a", "1")]), None);
+        let result = AsyncWasiModule::create(None, None, None);
         assert!(result.is_ok());
         let async_wasi_module = result.unwrap();
 
diff --git a/crates/wasmedge-sys/src/instance/function.rs b/crates/wasmedge-sys/src/instance/function.rs
index 972f7a581..367d0a546 100644
--- a/crates/wasmedge-sys/src/instance/function.rs
+++ b/crates/wasmedge-sys/src/instance/function.rs
@@ -5,170 +5,18 @@ use crate::{
 };
 #[cfg(all(feature = "async", target_os = "linux"))]
 use crate::{
-    r#async::{AsyncState, FiberFuture},
+    r#async::fiber::{AsyncCx, AsyncState, FiberFuture},
     BoxedAsyncFn, ASYNC_HOST_FUNCS,
 };
 use core::ffi::c_void;
 use parking_lot::Mutex;
 use rand::Rng;
-#[cfg(all(feature = "async", target_os = "linux"))]
-use std::pin::Pin;
 use std::{convert::TryInto, sync::Arc};
-#[cfg(all(feature = "async", target_os = "linux"))]
-use wasmedge_types::NeverType;
 use wasmedge_types::{
     error::{FuncError, HostFuncError, WasmEdgeError},
     ValType,
 };
 
-/// Defines the signature of an asynchronous host function.
-#[cfg(all(feature = "async", target_os = "linux"))]
-pub type AsyncHostFn<T> =
-    fn(
-        CallingFrame,
-        Vec<WasmValue>,
-        Option<&'static mut T>,
-    ) -> Box<dyn std::future::Future<Output = Result<Vec<WasmValue>, HostFuncError>> + Send>;
-
-/// Defines the signature of a host function.
-#[cfg(all(feature = "async", target_os = "linux"))]
-pub type HostFn<T> = fn(
-    CallingFrame,
-    Vec<WasmValue>,
-    Option<&'static mut T>,
-) -> Result<Vec<WasmValue>, HostFuncError>;
-
-#[cfg(all(feature = "async", target_os = "linux"))]
-extern "C" fn wrap_sync_wasi_fn<T: 'static>(
-    key_ptr: *mut c_void,
-    data: *mut std::os::raw::c_void,
-    call_frame_ctx: *const ffi::WasmEdge_CallingFrameContext,
-    params: *const ffi::WasmEdge_Value,
-    param_len: u32,
-    returns: *mut ffi::WasmEdge_Value,
-    return_len: u32,
-) -> ffi::WasmEdge_Result {
-    let frame = CallingFrame::create(call_frame_ctx);
-
-    // recover the async host function
-    let real_func: HostFn<T> = unsafe { std::mem::transmute(key_ptr) };
-
-    // recover the context data
-    let data = if std::any::TypeId::of::<T>() == std::any::TypeId::of::<NeverType>() {
-        None
-    } else {
-        let data: &'static mut T = unsafe { &mut *(data as *mut T) };
-        Some(data)
-    };
-
-    // input arguments
-    let input = {
-        let raw_input = unsafe {
-            std::slice::from_raw_parts(
-                params,
-                param_len
-                    .try_into()
-                    .expect("len of params should not greater than usize"),
-            )
-        };
-        raw_input.iter().map(|r| (*r).into()).collect::<Vec<_>>()
-    };
-
-    // returns
-    let return_len = return_len
-        .try_into()
-        .expect("len of returns should not greater than usize");
-    let raw_returns = unsafe { std::slice::from_raw_parts_mut(returns, return_len) };
-
-    match real_func(frame, input, data) {
-        Ok(returns) => {
-            assert!(returns.len() == return_len, "[wasmedge-sys] check the number of returns of host function. Expected: {}, actual: {}", return_len, returns.len());
-            for (idx, wasm_value) in returns.into_iter().enumerate() {
-                raw_returns[idx] = wasm_value.as_raw();
-            }
-            ffi::WasmEdge_Result { Code: 0 }
-        }
-        Err(err) => match err {
-            HostFuncError::User(code) => unsafe {
-                ffi::WasmEdge_ResultGen(ffi::WasmEdge_ErrCategory_UserLevelError, code)
-            },
-            HostFuncError::Runtime(code) => unsafe {
-                ffi::WasmEdge_ResultGen(ffi::WasmEdge_ErrCategory_WASM, code)
-            },
-        },
-    }
-}
-
-#[cfg(all(feature = "async", target_os = "linux"))]
-extern "C" fn wrap_async_wasi_fn<T: 'static>(
-    key_ptr: *mut c_void,
-    data: *mut std::os::raw::c_void,
-    call_frame_ctx: *const ffi::WasmEdge_CallingFrameContext,
-    params: *const ffi::WasmEdge_Value,
-    param_len: u32,
-    returns: *mut ffi::WasmEdge_Value,
-    return_len: u32,
-) -> ffi::WasmEdge_Result {
-    let frame = CallingFrame::create(call_frame_ctx);
-
-    // recover the async host function
-    let real_func: AsyncHostFn<T> = unsafe { std::mem::transmute(key_ptr) };
-
-    // recover the context data
-    let data = if std::any::TypeId::of::<T>() == std::any::TypeId::of::<NeverType>() {
-        None
-    } else {
-        let data: &'static mut T = unsafe { &mut *(data as *mut T) };
-        Some(data)
-    };
-
-    // arguments
-    let input = {
-        let raw_input = unsafe {
-            std::slice::from_raw_parts(
-                params,
-                param_len
-                    .try_into()
-                    .expect("len of params should not greater than usize"),
-            )
-        };
-        raw_input.iter().map(|r| (*r).into()).collect::<Vec<_>>()
-    };
-
-    // returns
-    let return_len = return_len
-        .try_into()
-        .expect("len of returns should not greater than usize");
-    let raw_returns = unsafe { std::slice::from_raw_parts_mut(returns, return_len) };
-
-    let async_cx = crate::r#async::AsyncCx::new();
-    let mut future = Pin::from(real_func(frame, input, data));
-    let result = match unsafe { async_cx.block_on(future.as_mut()) } {
-        Ok(Ok(ret)) => Ok(ret),
-        Ok(Err(err)) => Err(err),
-        Err(_err) => Err(HostFuncError::User(0x87)),
-    };
-
-    // parse result
-    match result {
-        Ok(returns) => {
-            assert!(returns.len() == return_len, "[wasmedge-sys] check the number of returns of async host function. Expected: {}, actual: {}", return_len, returns.len());
-            for (idx, wasm_value) in returns.into_iter().enumerate() {
-                raw_returns[idx] = wasm_value.as_raw();
-            }
-            ffi::WasmEdge_Result { Code: 0 }
-        }
-        Err(err) => match err {
-            HostFuncError::User(code) => unsafe {
-                ffi::WasmEdge_ResultGen(ffi::WasmEdge_ErrCategory_UserLevelError, code)
-            },
-            HostFuncError::Runtime(code) => unsafe {
-                ffi::WasmEdge_ResultGen(ffi::WasmEdge_ErrCategory_WASM, code)
-            },
-        },
-    }
-}
-
 pub type CustomFnWrapper = unsafe extern "C" fn(
     key_ptr: *mut c_void,
     data_ptr: *mut c_void,
@@ -280,7 +128,7 @@ extern "C" fn wrap_async_fn(
             drop(map_host_func);
 
             let frame = CallingFrame::create(call_frame_ctx);
-            let async_cx = crate::r#async::AsyncCx::new();
+            let async_cx = AsyncCx::new();
             let mut future = std::pin::Pin::from(real_fn_locked(frame, input, data));
             // call host function
             let result = match unsafe { async_cx.block_on(future.as_mut()) } {
@@ -380,11 +228,11 @@ impl Function {
     pub fn create_sync_func<T>(
         ty: &FuncType,
         real_fn: BoxedFn,
-        data: Option<&mut T>,
+        data: Option<Box<T>>,
         cost: u64,
     ) -> WasmEdgeResult<Self> {
         let data = match data {
-            Some(d) => d as *mut T as *mut std::os::raw::c_void,
+            Some(d) => Box::into_raw(d) as *mut std::ffi::c_void,
             None => std::ptr::null_mut(),
         };
 
@@ -553,68 +401,6 @@ impl Function {
         }
     }
 
-    #[cfg(all(feature = "async", target_os = "linux"))]
-    pub(crate) fn create_wasi_func<T>(
-        ty: &FuncType,
-        real_fn: HostFn<T>,
-        ctx_data: Option<&mut T>,
-        cost: u64,
-    ) -> WasmEdgeResult<Self> {
-        let data = match ctx_data {
-            Some(d) => d as *mut T as *mut std::os::raw::c_void,
-            None => std::ptr::null_mut(),
-        };
-
-        let ctx = unsafe {
-            ffi::WasmEdge_FunctionInstanceCreateBinding(
-                ty.inner.0,
-                Some(wrap_sync_wasi_fn::<T>),
-                real_fn as *mut _,
-                data,
-                cost,
-            )
-        };
-
-        match ctx.is_null() {
-            true => Err(Box::new(WasmEdgeError::Func(FuncError::Create))),
-            false => Ok(Self {
-                inner: Arc::new(Mutex::new(InnerFunc(ctx))),
-                registered: false,
-            }),
-        }
-    }
-
-    #[cfg(all(feature = "async", target_os = "linux"))]
-    pub(crate) fn create_async_wasi_func<T>(
-        ty: &FuncType,
-        real_fn: AsyncHostFn<T>,
-        ctx_data: Option<&mut T>,
-        cost: u64,
-    ) -> WasmEdgeResult<Self> {
-        let data = match ctx_data {
-            Some(d) => d as *mut T as *mut std::os::raw::c_void,
-            None => std::ptr::null_mut(),
-        };
-
-        let ctx = unsafe {
-            ffi::WasmEdge_FunctionInstanceCreateBinding(
-                ty.inner.0,
-                Some(wrap_async_wasi_fn::<T>),
-                real_fn as *mut _,
-                data,
-                cost,
-            )
-        };
-
-        match ctx.is_null() {
-            true => Err(Box::new(WasmEdgeError::Func(FuncError::Create))),
-            false => Ok(Self {
-                inner: Arc::new(Mutex::new(InnerFunc(ctx))),
-                registered: false,
-            }),
-        }
-    }
-
     /// Returns the underlying wasm type of this [Function].
     ///
     /// # Errors
@@ -929,794 +715,799 @@ pub(crate) struct InnerFuncRef(pub(crate) *const ffi::WasmEdge_FunctionInstanceC
 unsafe impl Send for InnerFuncRef {}
 unsafe impl Sync for InnerFuncRef {}
 
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::{
-        types::WasmValue, AsImport, Executor, ImportModule, ImportObject, Store,
-        HOST_FUNC_FOOTPRINTS,
-    };
-    #[cfg(all(feature = "async", target_os = "linux"))]
-    use crate::{AsyncWasiModule, ASYNC_HOST_FUNCS};
-    use std::{
-        sync::{Arc, Mutex},
-        thread,
-    };
-    use wasmedge_macro::sys_host_function;
-    use wasmedge_types::{NeverType, ValType};
-
-    #[test]
-    fn test_func_type() {
-        // test FuncType with args and returns
-        {
-            let param_tys = vec![
-                ValType::I32,
-                ValType::I64,
-                ValType::F32,
-                ValType::F64,
-                ValType::V128,
-                ValType::ExternRef,
-            ];
-            let param_len = param_tys.len();
-            let ret_tys = vec![ValType::FuncRef, ValType::ExternRef, ValType::V128];
-            let ret_len = ret_tys.len();
-
-            // create FuncType
-            let result = FuncType::create(param_tys, ret_tys);
-            assert!(result.is_ok());
-            let func_ty = result.unwrap();
-
-            // check parameters
-            assert_eq!(func_ty.params_len(), param_len as u32);
-            let param_tys = func_ty.params_type_iter().collect::<Vec<_>>();
-            assert_eq!(
-                param_tys,
-                vec![
-                    ValType::I32,
-                    ValType::I64,
-                    ValType::F32,
-                    ValType::F64,
-                    ValType::V128,
-                    ValType::ExternRef,
-                ]
-            );
-
-            // check returns
-            assert_eq!(func_ty.returns_len(), ret_len as u32);
-            let return_tys = func_ty.returns_type_iter().collect::<Vec<_>>();
-            assert_eq!(
-                return_tys,
-                vec![ValType::FuncRef, ValType::ExternRef, ValType::V128]
-            );
-        }
-
-        // test FuncType without args and returns
-        {
-            // create FuncType
-            let result = FuncType::create([], []);
-            assert!(result.is_ok());
-            let func_ty = result.unwrap();
-
-            assert_eq!(func_ty.params_len(), 0);
-            assert_eq!(func_ty.returns_len(), 0);
-        }
-    }
-
-    #[test]
-    fn test_func_basic() {
-        #[derive(Debug)]
-        struct Data<T, S> {
-            _x: i32,
-            _y: String,
-            _v: Vec<T>,
-            _s: Vec<S>,
-        }
-        let mut data: Data<i32, &str> = Data {
-            _x: 12,
-            _y: "hello".to_string(),
-            _v: vec![1, 2, 3],
-            _s: vec!["macos", "linux", "windows"],
-        };
-
-        #[sys_host_function]
-        fn real_add<T: core::fmt::Debug>(
-            _frame: CallingFrame,
-            input: Vec<WasmValue>,
-            data: &mut Data<i32, &str>,
-        ) -> Result<Vec<WasmValue>, HostFuncError> {
-            println!("Rust: Entering Rust function real_add");
-
-            println!("data: {:?}", data);
-
-            if input.len() != 2 {
-                return Err(HostFuncError::User(1));
-            }
-
-            let a = if input[0].ty() == ValType::I32 {
-                input[0].to_i32()
-            } else {
-                return Err(HostFuncError::User(2));
-            };
-
-            let b = if input[1].ty() == ValType::I32 {
-                input[1].to_i32()
-            } else {
-                return Err(HostFuncError::User(3));
-            };
-
-            let c = a + b;
-            println!("Rust: calcuating in real_add c: {c:?}");
-
-            println!("Rust: Leaving Rust function real_add");
-            Ok(vec![WasmValue::from_i32(c)])
-        }
-
-        assert_eq!(HOST_FUNCS.read().len(), 0);
-        assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 0);
-
-        // create a FuncType
-        let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]);
-        assert!(result.is_ok());
-        let func_ty = result.unwrap();
-        // create a host function
-        let result = Function::create_sync_func(&func_ty, Box::new(real_add), Some(&mut data), 0);
-        assert!(result.is_ok());
-        let host_func = result.unwrap();
-
-        // get func type
-        let result = host_func.ty();
-        assert!(result.is_ok());
-        let ty = result.unwrap();
-
-        // check parameters
-        assert_eq!(ty.params_len(), 2);
-        let param_tys = ty.params_type_iter().collect::<Vec<_>>();
-        assert_eq!(param_tys, vec![ValType::I32; 2]);
-
-        // check returns
-        assert_eq!(ty.returns_len(), 1);
-        let return_tys = ty.returns_type_iter().collect::<Vec<_>>();
-        assert_eq!(return_tys, vec![ValType::I32]);
-
-        // run this function
-        let result = Executor::create(None, None);
-        assert!(result.is_ok());
-        let mut executor = result.unwrap();
-        let result = host_func.call(
-            &mut executor,
-            vec![WasmValue::from_i32(1), WasmValue::from_i32(2)],
-        );
-        assert!(result.is_ok());
-        let returns = result.unwrap();
-        assert_eq!(returns[0].to_i32(), 3);
-    }
-
-    #[test]
-    #[allow(clippy::assertions_on_result_states)]
-    fn test_func_create_host_func_in_host_func() {
-        #[sys_host_function]
-        fn func(
-            _frame: CallingFrame,
-            _input: Vec<WasmValue>,
-        ) -> Result<Vec<WasmValue>, HostFuncError> {
-            println!("Entering host function: func");
-
-            // spawn a new thread to create a new host function
-            let handler = std::thread::spawn(|| {
-                #[sys_host_function]
-                fn real_add(
-                    _frame: CallingFrame,
-                    input: Vec<WasmValue>,
-                ) -> Result<Vec<WasmValue>, HostFuncError> {
-                    println!("Rust: Entering Rust function real_add");
-
-                    if input.len() != 2 {
-                        return Err(HostFuncError::User(1));
-                    }
-
-                    let a = if input[0].ty() == ValType::I32 {
-                        input[0].to_i32()
-                    } else {
-                        return Err(HostFuncError::User(2));
-                    };
-
-                    let b = if input[1].ty() == ValType::I32 {
-                        input[1].to_i32()
-                    } else {
-                        return Err(HostFuncError::User(3));
-                    };
-
-                    let c = a + b;
-
-                    println!("Rust: Leaving Rust function real_add");
-                    Ok(vec![WasmValue::from_i32(c)])
-                }
-
-                // create a FuncType
-                let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]);
-                assert!(result.is_ok());
-                let func_ty = result.unwrap();
-                // create a host function
-                let result =
-                    Function::create_sync_func::<NeverType>(&func_ty, Box::new(real_add), None, 0);
-                assert!(result.is_ok());
-                let host_func = result.unwrap();
-
-                // run this function
-                let result = Executor::create(None, None);
-                assert!(result.is_ok());
-                let mut executor = result.unwrap();
-                let result = host_func.call(
-                    &mut executor,
-                    vec![WasmValue::from_i32(1), WasmValue::from_i32(2)],
-                );
-                assert!(result.is_ok());
-                let returns = result.unwrap();
-                assert_eq!(returns[0].to_i32(), 3);
-            });
-            handler.join().unwrap();
-
-            println!("Leaving host function: func");
-            Ok(vec![])
-        }
-
-        // create a FuncType
-        let result = FuncType::create(vec![], vec![]);
-        assert!(result.is_ok());
-        let func_ty = result.unwrap();
-        // create a host function
-        let result = Function::create_sync_func::<NeverType>(&func_ty, Box::new(func), None, 0);
-        assert!(result.is_ok());
-        let host_func = result.unwrap();
-
-        // run this function
-        let result = Executor::create(None, None);
-        assert!(result.is_ok());
-        let mut executor = result.unwrap();
-        let result = host_func.call(&mut executor, vec![]);
-        assert!(result.is_ok());
-    }
-
-    #[test]
-    fn test_func_send() {
-        // create a FuncType
-        let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]);
-        assert!(result.is_ok());
-        let func_ty = result.unwrap();
-        // create a host function
-        let result = Function::create_sync_func::<NeverType>(&func_ty, Box::new(real_add), None, 0);
-        assert!(result.is_ok());
-        let host_func = result.unwrap();
-
-        let handle = thread::spawn(move || {
-            // get func type
-            let result = host_func.ty();
-            assert!(result.is_ok());
-            let ty = result.unwrap();
-
-            // check parameters
-            assert_eq!(ty.params_len(), 2);
-            let param_tys = ty.params_type_iter().collect::<Vec<_>>();
-            assert_eq!(param_tys, vec![ValType::I32; 2]);
-
-            // check returns
-            assert_eq!(ty.returns_len(), 1);
-            let return_tys = ty.returns_type_iter().collect::<Vec<_>>();
-            assert_eq!(return_tys, vec![ValType::I32]);
-        });
-
-        handle.join().unwrap()
-    }
-
-    #[test]
-    fn test_func_sync() {
-        // create a FuncType
-        let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]);
-        assert!(result.is_ok());
-        let func_ty = result.unwrap();
-        // create a host function
-        let result = Function::create_sync_func::<NeverType>(&func_ty, Box::new(real_add), None, 0);
-        assert!(result.is_ok());
-        let host_func = Arc::new(Mutex::new(result.unwrap()));
-
-        let host_func_cloned = Arc::clone(&host_func);
-        let handle = thread::spawn(move || {
-            let result = host_func_cloned.lock();
-            assert!(result.is_ok());
-            let host_func = result.unwrap();
-
-            // get func type
-            let result = host_func.ty();
-            assert!(result.is_ok());
-            let ty = result.unwrap();
-
-            // check parameters
-            assert_eq!(ty.params_len(), 2);
-            let param_tys = ty.params_type_iter().collect::<Vec<_>>();
-            assert_eq!(param_tys, vec![ValType::I32; 2]);
-
-            // check returns
-            assert_eq!(ty.returns_len(), 1);
-            let return_tys = ty.returns_type_iter().collect::<Vec<_>>();
-            assert_eq!(return_tys, vec![ValType::I32]);
-        });
-
-        handle.join().unwrap();
-    }
-
-    #[sys_host_function]
-    fn real_add(
-        _frame: CallingFrame,
-        input: Vec<WasmValue>,
-    ) -> Result<Vec<WasmValue>, HostFuncError> {
-        println!("Rust: Entering Rust function real_add");
-
-        if input.len() != 2 {
-            return Err(HostFuncError::User(1));
-        }
-
-        let a = if input[0].ty() == ValType::I32 {
-            input[0].to_i32()
-        } else {
-            return Err(HostFuncError::User(2));
-        };
-
-        let b = if input[1].ty() == ValType::I32 {
-            input[1].to_i32()
-        } else {
-            return Err(HostFuncError::User(3));
-        };
-
-        let c = a + b;
-        println!("Rust: calcuating in real_add c: {c:?}");
-
-        println!("Rust: Leaving Rust function real_add");
-        Ok(vec![WasmValue::from_i32(c)])
-    }
-
-    #[test]
-    fn test_func_closure() -> Result<(), Box<dyn std::error::Error>> {
-        {
-            // create a host function
-            let real_add = |_: CallingFrame,
-                            input: Vec<WasmValue>,
-                            _: *mut std::os::raw::c_void|
-             -> Result<Vec<WasmValue>, HostFuncError> {
-                println!("Rust: Entering Rust function real_add");
-
-                if input.len() != 2 {
-                    return Err(HostFuncError::User(1));
-                }
-
-                let a = if input[0].ty() == ValType::I32 {
-                    input[0].to_i32()
-                } else {
-                    return Err(HostFuncError::User(2));
-                };
-
-                let b = if input[1].ty() == ValType::I32 {
-                    input[1].to_i32()
-                } else {
-                    return Err(HostFuncError::User(3));
-                };
-
-                let c = a + b;
-                println!("Rust: calcuating in real_add c: {c:?}");
-
-                println!("Rust: Leaving Rust function real_add");
-                Ok(vec![WasmValue::from_i32(c)])
-            };
-
-            // create a FuncType
-            let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]);
-            assert!(result.is_ok());
-            let func_ty = result.unwrap();
-
-            // create a host function from the closure defined above
-            let result =
-                Function::create_sync_func::<NeverType>(&func_ty, Box::new(real_add), None, 0);
-            assert!(result.is_ok());
-            let host_func = result.unwrap();
-
-            // create a Store
-            let result = Store::create();
-            assert!(result.is_ok());
-            let mut store = result.unwrap();
-
-            // create an ImportModule
-            let mut import = ImportModule::create::<NeverType>("extern", None)?;
-            import.add_func("add", host_func);
-            let extern_import = ImportObject::Import(import);
-
-            // run this function
-            let result = Executor::create(None, None);
-            assert!(result.is_ok());
-            let mut executor = result.unwrap();
-            executor.register_import_object(&mut store, &extern_import)?;
-
-            let extern_instance = store.module("extern")?;
-            let add = extern_instance.get_func("add")?;
-
-            let result =
-                executor.call_func(&add, vec![WasmValue::from_i32(1), WasmValue::from_i32(2)]);
-            assert!(result.is_ok());
-            let returns = result.unwrap();
-            assert_eq!(returns[0].to_i32(), 3);
-        }
-
-        assert_eq!(HOST_FUNCS.read().len(), 0);
-        assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 0);
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_func_drop() -> Result<(), Box<dyn std::error::Error>> {
-        // create a host function
-        let real_add = |_: CallingFrame,
-                        input: Vec<WasmValue>,
-                        _: *mut std::os::raw::c_void|
-         -> Result<Vec<WasmValue>, HostFuncError> {
-            println!("Rust: Entering Rust function real_add");
-
-            if input.len() != 2 {
-                return Err(HostFuncError::User(1));
-            }
-
-            let a = if input[0].ty() == ValType::I32 {
-                input[0].to_i32()
-            } else {
-                return Err(HostFuncError::User(2));
-            };
-
-            let b = if input[1].ty() == ValType::I32 {
-                input[1].to_i32()
-            } else {
-                return Err(HostFuncError::User(3));
-            };
-
-            let c = a + b;
-            println!("Rust: calcuating in real_add c: {c:?}");
-
-            println!("Rust: Leaving Rust function real_add");
-            Ok(vec![WasmValue::from_i32(c)])
-        };
-
-        // create a FuncType
-        let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]);
-        assert!(result.is_ok());
-        let func_ty = result.unwrap();
-
-        // create a host function
-        let result = Function::create_sync_func::<NeverType>(&func_ty, Box::new(real_add), None, 0);
-        assert!(result.is_ok());
-        let host_func = result.unwrap();
-
-        assert_eq!(Arc::strong_count(&host_func.inner), 1);
-        assert!(!host_func.registered);
-
-        assert_eq!(HOST_FUNCS.read().len(), 1);
-        assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
-
-        // clone the host function before adding it to the import object
-        let host_func_cloned = host_func.clone();
-
-        assert_eq!(Arc::strong_count(&host_func_cloned.inner), 2);
-        assert!(!host_func_cloned.registered);
-
-        assert_eq!(HOST_FUNCS.read().len(), 1);
-        assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
-
-        // create an ImportModule
-        let mut import_module = ImportModule::create::<NeverType>("extern", None)?;
-        // add the host function to the import module
-        import_module.add_func("add", host_func);
-
-        assert_eq!(Arc::strong_count(&host_func_cloned.inner), 2);
-        assert!(!host_func_cloned.registered);
-
-        assert_eq!(HOST_FUNCS.read().len(), 1);
-        assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
-
-        drop(host_func_cloned);
-
-        assert_eq!(HOST_FUNCS.read().len(), 1);
-        assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
-
-        let import = ImportObject::Import(import_module);
-
-        // create a Store
-        let result = Store::create();
-        assert!(result.is_ok());
-        let mut store = result.unwrap();
-
-        // run this function
-        let result = Executor::create(None, None);
-        assert!(result.is_ok());
-        let mut executor = result.unwrap();
-        executor.register_import_object(&mut store, &import)?;
-
-        // get the registered host function
-        let extern_instance = store.module("extern")?;
-        let add = extern_instance.get_func("add")?;
-        assert_eq!(Arc::strong_count(&add.inner), 1);
-        assert!(add.registered);
-
-        assert_eq!(HOST_FUNCS.read().len(), 1);
-        assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
-
-        // clone the host function
-        let add_cloned = add.clone();
-        assert_eq!(Arc::strong_count(&add.inner), 2);
-        assert!(add.registered);
-        assert_eq!(Arc::strong_count(&add_cloned.inner), 2);
-        assert!(add_cloned.registered);
-
-        assert_eq!(HOST_FUNCS.read().len(), 1);
-        assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
-
-        // drop the cloned host function
-        drop(add_cloned);
-        assert_eq!(Arc::strong_count(&add.inner), 1);
-        assert!(add.registered);
-
-        assert_eq!(HOST_FUNCS.read().len(), 1);
-        assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
-
-        drop(add);
-
-        assert_eq!(HOST_FUNCS.read().len(), 1);
-        assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
-
-        // get the registered host function again
-        let extern_instance = store.module("extern")?;
-        let add_again = extern_instance.get_func("add")?;
-        assert_eq!(Arc::strong_count(&add_again.inner), 1);
-        assert!(add_again.registered);
-
-        assert_eq!(HOST_FUNCS.read().len(), 1);
-        assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
-
-        // ! notice that `add_again` should be dropped before or not be used after dropping `import`
-        drop(add_again);
-
-        assert_eq!(HOST_FUNCS.read().len(), 1);
-        assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
-
-        // drop the import object
-        drop(import);
-
-        assert!(store.module("extern").is_err());
-
-        assert_eq!(HOST_FUNCS.read().len(), 0);
-        assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 0);
-
-        // ! if `add_again` is not dropped before dropping `import`, then calling `add_again` will crash
-        // let result = executor.call_func(
-        //     &add_again,
-        //     vec![WasmValue::from_i32(1), WasmValue::from_i32(2)],
-        // );
-
-        Ok(())
-    }
-
-    #[cfg(all(feature = "async", target_os = "linux"))]
-    #[tokio::test]
-    async fn test_func_async_closure() -> Result<(), Box<dyn std::error::Error>> {
-        {
-            #[derive(Debug)]
-            struct Data<T, S> {
-                _x: i32,
-                _y: String,
-                _v: Vec<T>,
-                _s: Vec<S>,
-            }
-            impl<T, S> Drop for Data<T, S> {
-                fn drop(&mut self) {
-                    println!("Dropping Data");
-                }
-            }
-
-            let data: Data<i32, &str> = Data {
-                _x: 12,
-                _y: "hello".to_string(),
-                _v: vec![1, 2, 3],
-                _s: vec!["macos", "linux", "windows"],
-            };
-
-            // define an async closure
-            let c = |_frame: CallingFrame,
-                     _args: Vec<WasmValue>,
-                     data: *mut std::os::raw::c_void|
-             -> Box<
-                (dyn std::future::Future<Output = Result<Vec<WasmValue>, HostFuncError>> + Send),
-            > {
-                // let host_data = unsafe { &mut *(data as *mut Data<i32, &str>) };
-                let host_data = unsafe { Box::from_raw(data as *mut Data<i32, &str>) };
-
-                Box::new(async move {
-                    for _ in 0..10 {
-                        println!("[async hello] say hello");
-                        tokio::time::sleep(std::time::Duration::from_secs(1)).await;
-
-                        println!("host_data: {:?}", host_data);
-                    }
-
-                    println!("[async hello] Done!");
-
-                    Ok(vec![])
-                })
-            };
-
-            // create a FuncType
-            let result = FuncType::create(vec![], vec![]);
-            assert!(result.is_ok());
-            let func_ty = result.unwrap();
-
-            // create an async host function
-            let result =
-                Function::create_async_func(&func_ty, Box::new(c), Some(Box::new(data)), 0);
-            assert!(result.is_ok());
-            let async_hello_func = result.unwrap();
-
-            // create an Executor
-            let result = Executor::create(None, None);
-            assert!(result.is_ok());
-            let mut executor = result.unwrap();
-            assert!(!executor.inner.0.is_null());
-
-            // create a Store
-            let result = Store::create();
-            assert!(result.is_ok());
-            let mut store = result.unwrap();
-
-            // create an AsyncWasiModule
-            let result = AsyncWasiModule::create(Some(vec!["abc"]), Some(vec![("a", "1")]), None);
-            assert!(result.is_ok());
-            let async_wasi_module = result.unwrap();
-
-            // register async_wasi module into the store
-            let wasi_import = ImportObject::AsyncWasi(async_wasi_module);
-            let result = executor.register_import_object(&mut store, &wasi_import);
-            assert!(result.is_ok());
-
-            // create an ImportModule
-            let mut import = ImportModule::create::<NeverType>("extern", None)?;
-            import.add_func("async_hello", async_hello_func);
-
-            let extern_import = ImportObject::Import(import);
-            executor.register_import_object(&mut store, &extern_import)?;
-
-            let extern_instance = store.module("extern")?;
-            let async_hello = extern_instance.get_func("async_hello")?;
-
-            async fn tick() {
-                let mut i = 0;
-                loop {
-                    println!("[tick] i={i}");
-                    tokio::time::sleep(std::time::Duration::from_millis(500)).await;
-                    i += 1;
-                }
-            }
-            tokio::spawn(tick());
-
-            let async_state = AsyncState::new();
-            let _ = executor
-                .call_func_async(&async_state, &async_hello, [])
-                .await?;
-        }
-
-        assert_eq!(ASYNC_HOST_FUNCS.read().len(), 0);
-        assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 0);
-
-        Ok(())
-    }
-
-    #[cfg(all(feature = "async", target_os = "linux"))]
-    #[tokio::test]
-    async fn test_func_async_func() -> Result<(), Box<dyn std::error::Error>> {
-        {
-            #[derive(Debug)]
-            struct Data<T, S> {
-                _x: i32,
-                _y: String,
-                _v: Vec<T>,
-                _s: Vec<S>,
-            }
-            let data: Data<i32, &str> = Data {
-                _x: 12,
-                _y: "hello".to_string(),
-                _v: vec![1, 2, 3],
-                _s: vec!["macos", "linux", "windows"],
-            };
-
-            // define async host function
-            fn f<T: core::fmt::Debug + Send + Sync + 'static>(
-                _frame: CallingFrame,
-                _args: Vec<WasmValue>,
-                data: *mut std::ffi::c_void,
-            ) -> Box<(dyn std::future::Future<Output = Result<Vec<WasmValue>, HostFuncError>> + Send)>
-            {
-                let data = unsafe { Box::from_raw(data as *mut T) };
-
-                Box::new(async move {
-                    for _ in 0..10 {
-                        println!("[async hello] say hello");
-                        tokio::time::sleep(std::time::Duration::from_secs(1)).await;
-                        println!("host_data: {:?}", data);
-                    }
-
-                    println!("[async hello] Done!");
-
-                    Ok(vec![])
-                })
-            }
-
-            // create a FuncType
-            let result = FuncType::create(vec![], vec![]);
-            assert!(result.is_ok());
-            let func_ty = result.unwrap();
-
-            // create an async host function
-            let result = Function::create_async_func(
-                &func_ty,
-                Box::new(f::<Data<i32, &str>>),
-                Some(Box::new(data)),
-                0,
-            );
-            assert!(result.is_ok());
-            let async_hello_func = result.unwrap();
-
-            // create an Executor
-            let result = Executor::create(None, None);
-            assert!(result.is_ok());
-            let mut executor = result.unwrap();
-            assert!(!executor.inner.0.is_null());
-
-            // create a Store
-            let result = Store::create();
-            assert!(result.is_ok());
-            let mut store = result.unwrap();
-
-            // create an AsyncWasiModule
-            let result = AsyncWasiModule::create(Some(vec!["abc"]), Some(vec![("a", "1")]), None);
-            assert!(result.is_ok());
-            let async_wasi_module = result.unwrap();
-
-            // register async_wasi module into the store
-            let wasi_import = ImportObject::AsyncWasi(async_wasi_module);
-            let result = executor.register_import_object(&mut store, &wasi_import);
-            assert!(result.is_ok());
-
-            // create an ImportModule
-            let mut import = ImportModule::create::<NeverType>("extern", None)?;
-            import.add_func("async_hello", async_hello_func);
-
-            let extern_import = ImportObject::Import(import);
-            executor.register_import_object(&mut store, &extern_import)?;
-
-            let extern_instance = store.module("extern")?;
-            let async_hello = extern_instance.get_func("async_hello")?;
-
-            async fn tick() {
-                let mut i = 0;
-                loop {
-                    println!("[tick] i={i}");
-                    tokio::time::sleep(std::time::Duration::from_millis(500)).await;
-                    i += 1;
-                }
-            }
-            tokio::spawn(tick());
-
-            let async_state = AsyncState::new();
-            let _ = executor
-                .call_func_async(&async_state, &async_hello, [])
-                .await?;
-        }
-
-        assert_eq!(ASYNC_HOST_FUNCS.read().len(), 0);
-        assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 0);
-
-        Ok(())
-    }
-}
+// #[cfg(test)]
+// mod tests {
+//     use super::*;
+//     #[cfg(all(feature = "async", target_os = "linux"))]
+//     use crate::{r#async::AsyncWasiModule, ASYNC_HOST_FUNCS};
+//     use crate::{
+//         types::WasmValue, AsImport, Executor, ImportModule, ImportObject, Store,
+//         HOST_FUNC_FOOTPRINTS,
+//     };
+//     use std::{
+//         sync::{Arc, Mutex},
+//         thread,
+//     };
+//     use wasmedge_macro::sys_host_function;
+//     use wasmedge_types::{NeverType, ValType};
+
+//     #[test]
+//     fn test_func_type() {
+//         // test FuncType with args and returns
+//         {
+//             let param_tys = vec![
+//                 ValType::I32,
+//                 ValType::I64,
+//                 ValType::F32,
+//                 ValType::F64,
+//                 ValType::V128,
+//                 ValType::ExternRef,
+//             ];
+//             let param_len = param_tys.len();
+//             let ret_tys = vec![ValType::FuncRef, ValType::ExternRef, ValType::V128];
+//             let ret_len = ret_tys.len();
+
+//             // create FuncType
+//             let result = FuncType::create(param_tys, ret_tys);
+//             assert!(result.is_ok());
+//             let func_ty = result.unwrap();
+
+//             // check parameters
+//             assert_eq!(func_ty.params_len(), param_len as u32);
+//             let param_tys = func_ty.params_type_iter().collect::<Vec<_>>();
+//             assert_eq!(
+//                 param_tys,
+//                 vec![
+//                     ValType::I32,
+//                     ValType::I64,
+//                     ValType::F32,
+//                     ValType::F64,
+//                     ValType::V128,
+//                     ValType::ExternRef,
+//                 ]
+//             );
+
+//             // check returns
+//             assert_eq!(func_ty.returns_len(), ret_len as u32);
+//             let return_tys = func_ty.returns_type_iter().collect::<Vec<_>>();
+//             assert_eq!(
+//                 return_tys,
+//                 vec![ValType::FuncRef, ValType::ExternRef, ValType::V128]
+//             );
+//         }
+
+//         // test FuncType without args and returns
+//         {
+//             // create FuncType
+//             let result = FuncType::create([], []);
+//             assert!(result.is_ok());
+//             let func_ty = result.unwrap();
+
+//             assert_eq!(func_ty.params_len(), 0);
+//             assert_eq!(func_ty.returns_len(), 0);
+//         }
+//     }
+
+//     #[test]
+//     fn test_func_basic() {
+//         #[derive(Debug)]
+//         struct Data<T, S> {
+//             _x: i32,
+//             _y: String,
+//             _v: Vec<T>,
+//             _s: Vec<S>,
+//         }
+//         let data: Data<i32, &str> = Data {
+//             _x: 12,
+//             _y: "hello".to_string(),
+//             _v: vec![1, 2, 3],
+//             _s: vec!["macos", "linux", "windows"],
+//         };
+
+//         fn real_add<T: core::fmt::Debug>(
+//             _frame: CallingFrame,
+//             input: Vec<WasmValue>,
+//             data: *mut std::ffi::c_void,
+//         ) -> Result<Vec<WasmValue>, HostFuncError> {
+//             println!("Rust: Entering Rust function real_add");
+
+//             let host_data = unsafe { Box::from_raw(data as *mut T) };
+//             println!("host_data: {:?}", host_data);
+
+//             if input.len() != 2 {
+//                 return Err(HostFuncError::User(1));
+//             }
+
+//             let a = if input[0].ty() == ValType::I32 {
+//                 input[0].to_i32()
+//             } else {
+//                 return Err(HostFuncError::User(2));
+//             };
+
+//             let b = if input[1].ty() == ValType::I32 {
+//                 input[1].to_i32()
+//             } else {
+//                 return Err(HostFuncError::User(3));
+//             };
+
+//             let c = a + b;
+//             println!("Rust: calcuating in real_add c: {c:?}");
+
+//             println!("Rust: Leaving Rust function real_add");
+//             Ok(vec![WasmValue::from_i32(c)])
+//         }
+
+//         assert_eq!(HOST_FUNCS.read().len(), 0);
+//         assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 0);
+
+//         // create a FuncType
+//         let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]);
+//         assert!(result.is_ok());
+//         let func_ty = result.unwrap();
+//         // create a host function
+//         let result = Function::create_sync_func(
+//             &func_ty,
+//             Box::new(real_add::<Data<i32, &str>>),
+//             Some(Box::new(data)),
+//             0,
+//         );
+//         assert!(result.is_ok());
+//         let host_func = result.unwrap();
+
+//         // get func type
+//         let result = host_func.ty();
+//         assert!(result.is_ok());
+//         let ty = result.unwrap();
+
+//         // check parameters
+//         assert_eq!(ty.params_len(), 2);
+//         let param_tys = ty.params_type_iter().collect::<Vec<_>>();
+//         assert_eq!(param_tys, vec![ValType::I32; 2]);
+
+//         // check returns
+//         assert_eq!(ty.returns_len(), 1);
+//         let return_tys = ty.returns_type_iter().collect::<Vec<_>>();
+//         assert_eq!(return_tys, vec![ValType::I32]);
+
+//         // run this function
+//         let result = Executor::create(None, None);
+//         assert!(result.is_ok());
+//         let mut executor = result.unwrap();
+//         let result = host_func.call(
+//             &mut executor,
+//             vec![WasmValue::from_i32(1), WasmValue::from_i32(2)],
+//         );
+//         assert!(result.is_ok());
+//         let returns = result.unwrap();
+//         assert_eq!(returns[0].to_i32(), 3);
+//     }
+
+//     #[test]
+//     #[allow(clippy::assertions_on_result_states)]
+//     fn test_func_create_host_func_in_host_func() {
+//         #[sys_host_function]
+//         fn func(
+//             _frame: CallingFrame,
+//             _input: Vec<WasmValue>,
+//         ) -> Result<Vec<WasmValue>, HostFuncError> {
+//             println!("Entering host function: func");
+
+//             // spawn a new thread to create a new host function
+//             let handler = std::thread::spawn(|| {
+//                 #[sys_host_function]
+//                 fn real_add(
+//                     _frame: CallingFrame,
+//                     input: Vec<WasmValue>,
+//                 ) -> Result<Vec<WasmValue>, HostFuncError> {
+//                     println!("Rust: Entering Rust function real_add");
+
+//                     if input.len() != 2 {
+//                         return Err(HostFuncError::User(1));
+//                     }
+
+//                     let a = if input[0].ty() == ValType::I32 {
+//                         input[0].to_i32()
+//                     } else {
+//                         return Err(HostFuncError::User(2));
+//                     };
+
+//                     let b = if input[1].ty() == ValType::I32 {
+//                         input[1].to_i32()
+//                     } else {
+//                         return Err(HostFuncError::User(3));
+//                     };
+
+//                     let c = a + b;
+
+//                     println!("Rust: Leaving Rust function real_add");
+//                     Ok(vec![WasmValue::from_i32(c)])
+//                 }
+
+//                 // create a FuncType
+//                 let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]);
+//                 assert!(result.is_ok());
+//                 let func_ty = result.unwrap();
+//                 // create a host function
+//                 let result =
+//                     Function::create_sync_func::<NeverType>(&func_ty, Box::new(real_add), None, 0);
+//                 assert!(result.is_ok());
+//                 let host_func = result.unwrap();
+
+//                 // run this function
+//                 let result = Executor::create(None, None);
+//                 assert!(result.is_ok());
+//                 let mut executor = result.unwrap();
+//                 let result = host_func.call(
+//                     &mut executor,
+//                     vec![WasmValue::from_i32(1), WasmValue::from_i32(2)],
+//                 );
+//                 assert!(result.is_ok());
+//                 let returns = result.unwrap();
+//                 assert_eq!(returns[0].to_i32(), 3);
+//             });
+//             handler.join().unwrap();
+
+//             println!("Leaving host function: func");
+//             Ok(vec![])
+//         }
+
+//         // create a FuncType
+//         let result = FuncType::create(vec![], vec![]);
+//         assert!(result.is_ok());
+//         let func_ty = result.unwrap();
+//         // create a host function
+//         let result = Function::create_sync_func::<NeverType>(&func_ty, Box::new(func), None, 0);
+//         assert!(result.is_ok());
+//         let host_func = result.unwrap();
+
+//         // run this function
+//         let result = Executor::create(None, None);
+//         assert!(result.is_ok());
+//         let mut executor = result.unwrap();
+//         let result = host_func.call(&mut executor, vec![]);
+//         assert!(result.is_ok());
+//     }
+
+//     #[test]
+//     fn test_func_send() {
+//         // create a FuncType
+//         let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]);
+//         assert!(result.is_ok());
+//         let func_ty = result.unwrap();
+//         // create a host function
+//         let result = Function::create_sync_func::<NeverType>(&func_ty, Box::new(real_add), None, 0);
+//         assert!(result.is_ok());
+//         let host_func = result.unwrap();
+
+//         let handle = thread::spawn(move || {
+//             // get func type
+//             let result = host_func.ty();
+//             assert!(result.is_ok());
+//             let ty = result.unwrap();
+
+//             // check parameters
+//             assert_eq!(ty.params_len(), 2);
+//             let param_tys = ty.params_type_iter().collect::<Vec<_>>();
+//             assert_eq!(param_tys, vec![ValType::I32; 2]);
+
+//             // check returns
+//             assert_eq!(ty.returns_len(), 1);
+//             let return_tys = ty.returns_type_iter().collect::<Vec<_>>();
+//             assert_eq!(return_tys, vec![ValType::I32]);
+//         });
+
+//         handle.join().unwrap()
+//     }
+
+//     #[test]
+//     fn test_func_sync() {
+//         // create a FuncType
+//         let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]);
+//         assert!(result.is_ok());
+//         let func_ty = result.unwrap();
+//         // create a host function
+//         let result = Function::create_sync_func::<NeverType>(&func_ty, Box::new(real_add), None, 0);
+//         assert!(result.is_ok());
+//         let host_func = Arc::new(Mutex::new(result.unwrap()));
+
+//         let host_func_cloned = Arc::clone(&host_func);
+//         let handle = thread::spawn(move || {
+//             let result = host_func_cloned.lock();
+//             assert!(result.is_ok());
+//             let host_func = result.unwrap();
+
+//             // get func type
+//             let result = host_func.ty();
+//             assert!(result.is_ok());
+//             let ty = result.unwrap();
+
+//             // check parameters
+//             assert_eq!(ty.params_len(), 2);
+//             let param_tys = ty.params_type_iter().collect::<Vec<_>>();
+//             assert_eq!(param_tys, vec![ValType::I32; 2]);
+
+//             // check returns
+//             assert_eq!(ty.returns_len(), 1);
+//             let return_tys = ty.returns_type_iter().collect::<Vec<_>>();
+//             assert_eq!(return_tys, vec![ValType::I32]);
+//         });
+
+//         handle.join().unwrap();
+//     }
+
+//     #[sys_host_function]
+//     fn real_add(
+//         _frame: CallingFrame,
+//         input: Vec<WasmValue>,
+//     ) -> Result<Vec<WasmValue>, HostFuncError> {
+//         println!("Rust: Entering Rust function real_add");
+
+//         if input.len() != 2 {
+//             return Err(HostFuncError::User(1));
+//         }
+
+//         let a = if input[0].ty() == ValType::I32 {
+//             input[0].to_i32()
+//         } else {
+//             return Err(HostFuncError::User(2));
+//         };
+
+//         let b = if input[1].ty() == ValType::I32 {
+//             input[1].to_i32()
+//         } else {
+//             return Err(HostFuncError::User(3));
+//         };
+
+//         let c = a + b;
+//         println!("Rust: calcuating in real_add c: {c:?}");
+
+//         println!("Rust: Leaving Rust function real_add");
+//         Ok(vec![WasmValue::from_i32(c)])
+//     }
+
+//     #[test]
+//     fn test_func_closure() -> Result<(), Box<dyn std::error::Error>> {
+//         {
+//             // create a host function
+//             let real_add = |_: CallingFrame,
+//                             input: Vec<WasmValue>,
+//                             _: *mut std::os::raw::c_void|
+//              -> Result<Vec<WasmValue>, HostFuncError> {
+//                 println!("Rust: Entering Rust function real_add");
+
+//                 if input.len() != 2 {
+//                     return Err(HostFuncError::User(1));
+//                 }
+
+//                 let a = if input[0].ty() == ValType::I32 {
+//                     input[0].to_i32()
+//                 } else {
+//                     return Err(HostFuncError::User(2));
+//                 };
+
+//                 let b = if input[1].ty() == ValType::I32 {
+//                     input[1].to_i32()
+//                 } else {
+//                     return Err(HostFuncError::User(3));
+//                 };
+
+//                 let c = a + b;
+//                 println!("Rust: calcuating in real_add c: {c:?}");
+
+//                 println!("Rust: Leaving Rust function real_add");
+//                 Ok(vec![WasmValue::from_i32(c)])
+//             };
+
+//             // create a FuncType
+//             let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]);
+//             assert!(result.is_ok());
+//             let func_ty = result.unwrap();
+
+//             // create a host function from the closure defined above
+//             let result =
+//                 Function::create_sync_func::<NeverType>(&func_ty, Box::new(real_add), None, 0);
+//             assert!(result.is_ok());
+//             let host_func = result.unwrap();
+
+//             // create a Store
+//             let result = Store::create();
+//             assert!(result.is_ok());
+//             let mut store = result.unwrap();
+
+//             // create an ImportModule
+//             let mut import = ImportModule::create::<NeverType>("extern", None)?;
+//             import.add_func("add", host_func);
+//             let extern_import = ImportObject::Import(import);
+
+//             // run this function
+//             let result = Executor::create(None, None);
+//             assert!(result.is_ok());
+//             let mut executor = result.unwrap();
+//             executor.register_import_object(&mut store, &extern_import)?;
+
+//             let extern_instance = store.module("extern")?;
+//             let add = extern_instance.get_func("add")?;
+
+//             let result =
+//                 executor.call_func(&add, vec![WasmValue::from_i32(1), WasmValue::from_i32(2)]);
+//             assert!(result.is_ok());
+//             let returns = result.unwrap();
+//             assert_eq!(returns[0].to_i32(), 3);
+//         }
+
+//         assert_eq!(HOST_FUNCS.read().len(), 0);
+//         assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 0);
+
+//         Ok(())
+//     }
+
+//     #[test]
+//     fn test_func_drop() -> Result<(), Box<dyn std::error::Error>> {
+//         // create a host function
+//         let real_add = |_: CallingFrame,
+//                         input: Vec<WasmValue>,
+//                         _: *mut std::os::raw::c_void|
+//          -> Result<Vec<WasmValue>, HostFuncError> {
+//             println!("Rust: Entering Rust function real_add");
+
+//             if input.len() != 2 {
+//                 return Err(HostFuncError::User(1));
+//             }
+
+//             let a = if input[0].ty() == ValType::I32 {
+//                 input[0].to_i32()
+//             } else {
+//                 return Err(HostFuncError::User(2));
+//             };
+
+//             let b = if input[1].ty() == ValType::I32 {
+//                 input[1].to_i32()
+//             } else {
+//                 return Err(HostFuncError::User(3));
+//             };
+
+//             let c = a + b;
+//             println!("Rust: calcuating in real_add c: {c:?}");
+
+//             println!("Rust: Leaving Rust function real_add");
+//             Ok(vec![WasmValue::from_i32(c)])
+//         };
+
+//         // create a FuncType
+//         let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]);
+//         assert!(result.is_ok());
+//         let func_ty = result.unwrap();
+
+//         // create a host function
+//         let result = Function::create_sync_func::<NeverType>(&func_ty, Box::new(real_add), None, 0);
+//         assert!(result.is_ok());
+//         let host_func = result.unwrap();
+
+//         assert_eq!(Arc::strong_count(&host_func.inner), 1);
+//         assert!(!host_func.registered);
+
+//         assert_eq!(HOST_FUNCS.read().len(), 1);
+//         assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
+
+//         // clone the host function before adding it to the import object
+//         let host_func_cloned = host_func.clone();
+
+//         assert_eq!(Arc::strong_count(&host_func_cloned.inner), 2);
+//         assert!(!host_func_cloned.registered);
+
+//         assert_eq!(HOST_FUNCS.read().len(), 1);
+//         assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
+
+//         // create an ImportModule
+//         let mut import_module = ImportModule::create::<NeverType>("extern", None)?;
+//         // add the host function to the import module
+//         import_module.add_func("add", host_func);
+
+//         assert_eq!(Arc::strong_count(&host_func_cloned.inner), 2);
+//         assert!(!host_func_cloned.registered);
+
+//         assert_eq!(HOST_FUNCS.read().len(), 1);
+//         assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
+
+//         drop(host_func_cloned);
+
+//         assert_eq!(HOST_FUNCS.read().len(), 1);
+//         assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
+
+//         let import = ImportObject::Import(import_module);
+
+//         // create a Store
+//         let result = Store::create();
+//         assert!(result.is_ok());
+//         let mut store = result.unwrap();
+
+//         // run this function
+//         let result = Executor::create(None, None);
+//         assert!(result.is_ok());
+//         let mut executor = result.unwrap();
+//         executor.register_import_object(&mut store, &import)?;
+
+//         // get the registered host function
+//         let extern_instance = store.module("extern")?;
+//         let add = extern_instance.get_func("add")?;
+//         assert_eq!(Arc::strong_count(&add.inner), 1);
+//         assert!(add.registered);
+
+//         assert_eq!(HOST_FUNCS.read().len(), 1);
+//         assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
+
+//         // clone the host function
+//         let add_cloned = add.clone();
+//         assert_eq!(Arc::strong_count(&add.inner), 2);
+//         assert!(add.registered);
+//         assert_eq!(Arc::strong_count(&add_cloned.inner), 2);
+//         assert!(add_cloned.registered);
+
+//         assert_eq!(HOST_FUNCS.read().len(), 1);
+//         assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
+
+//         // drop the cloned host function
+//         drop(add_cloned);
+//         assert_eq!(Arc::strong_count(&add.inner), 1);
+//         assert!(add.registered);
+
+//         assert_eq!(HOST_FUNCS.read().len(), 1);
+//         assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
+
+//         drop(add);
+
+//         assert_eq!(HOST_FUNCS.read().len(), 1);
+//         assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
+
+//         // get the registered host function again
+//         let extern_instance = store.module("extern")?;
+//         let add_again = extern_instance.get_func("add")?;
+//         assert_eq!(Arc::strong_count(&add_again.inner), 1);
+//         assert!(add_again.registered);
+
+//         assert_eq!(HOST_FUNCS.read().len(), 1);
+//         assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
+
+//         // ! notice that `add_again` should be dropped before or not be used after dropping `import`
+//         drop(add_again);
+
+//         assert_eq!(HOST_FUNCS.read().len(), 1);
+//         assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1);
+
+//         // drop the import object
+//         drop(import);
+
+//         assert!(store.module("extern").is_err());
+
+//         assert_eq!(HOST_FUNCS.read().len(), 0);
+//         assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 0);
+
+//         // ! if `add_again` is not dropped before dropping `import`, then calling `add_again` will crash
+//         // let result = executor.call_func(
+//         //     &add_again,
+//         //     vec![WasmValue::from_i32(1), WasmValue::from_i32(2)],
+//         // );
+
+//         Ok(())
+//     }
+
+//     #[cfg(all(feature = "async", target_os = "linux"))]
+//     #[tokio::test]
+//     async fn test_func_async_closure() -> Result<(), Box<dyn std::error::Error>> {
+//         {
+//             #[derive(Debug)]
+//             struct Data<T, S> {
+//                 _x: i32,
+//                 _y: String,
+//                 _v: Vec<T>,
+//                 _s: Vec<S>,
+//             }
+//             impl<T, S> Drop for Data<T, S> {
+//                 fn drop(&mut self) {
+//                     println!("Dropping Data");
+//                 }
+//             }
+
+//             let data: Data<i32, &str> = Data {
+//                 _x: 12,
+//                 _y: "hello".to_string(),
+//                 _v: vec![1, 2, 3],
+//                 _s: vec!["macos", "linux", "windows"],
+//             };
+
+//             // define an async closure
+//             let c = |_frame: CallingFrame,
+//                      _args: Vec<WasmValue>,
+//                      data: *mut std::os::raw::c_void|
+//              -> Box<
+//                 (dyn std::future::Future<Output = Result<Vec<WasmValue>, HostFuncError>> + Send),
+//             > {
+//                 // let host_data = unsafe { &mut *(data as *mut Data<i32, &str>) };
+//                 let host_data = unsafe { Box::from_raw(data as *mut Data<i32, &str>) };
+
+//                 Box::new(async move {
+//                     for _ in 0..10 {
+//                         println!("[async hello] say hello");
+//                         tokio::time::sleep(std::time::Duration::from_secs(1)).await;
+
+//                         println!("host_data: {:?}", host_data);
+//                     }
+
+//                     println!("[async hello] Done!");
+
+//                     Ok(vec![])
+//                 })
+//             };
+
+//             // create a FuncType
+//             let result = FuncType::create(vec![], vec![]);
+//             assert!(result.is_ok());
+//             let func_ty = result.unwrap();
+
+//             // create an async host function
+//             let result =
+//                 Function::create_async_func(&func_ty, Box::new(c), Some(Box::new(data)), 0);
+//             assert!(result.is_ok());
+//             let async_hello_func = result.unwrap();
+
+//             // create an Executor
+//             let result = Executor::create(None, None);
+//             assert!(result.is_ok());
+//             let mut executor = result.unwrap();
+//             assert!(!executor.inner.0.is_null());
+
+//             // create a Store
+//             let result = Store::create();
+//             assert!(result.is_ok());
+//             let mut store = result.unwrap();
+
+//             // create an AsyncWasiModule
+//             let result = AsyncWasiModule::create(Some(vec!["abc"]), Some(vec![("a", "1")]), None);
+//             assert!(result.is_ok());
+//             let async_wasi_module = result.unwrap();
+
+//             // register async_wasi module into the store
+//             let wasi_import = ImportObject::AsyncWasi(async_wasi_module);
+//             let result = executor.register_import_object(&mut store, &wasi_import);
+//             assert!(result.is_ok());
+
+//             // create an ImportModule
+//             let mut import = ImportModule::create::<NeverType>("extern", None)?;
+//             import.add_func("async_hello", async_hello_func);
+
+//             let extern_import = ImportObject::Import(import);
+//             executor.register_import_object(&mut store, &extern_import)?;
+
+//             let extern_instance = store.module("extern")?;
+//             let async_hello = extern_instance.get_func("async_hello")?;
+
+//             async fn tick() {
+//                 let mut i = 0;
+//                 loop {
+//                     println!("[tick] i={i}");
+//                     tokio::time::sleep(std::time::Duration::from_millis(500)).await;
+//                     i += 1;
+//                 }
+//             }
+//             tokio::spawn(tick());
+
+//             let async_state = AsyncState::new();
+//             let _ = executor
+//                 .call_func_async(&async_state, &async_hello, [])
+//                 .await?;
+//         }
+
+//         assert_eq!(ASYNC_HOST_FUNCS.read().len(), 0);
+//         assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 0);
+
+//         Ok(())
+//     }
+
+//     #[cfg(all(feature = "async", target_os = "linux"))]
+//     #[tokio::test]
+//     async fn test_func_async_func() -> Result<(), Box<dyn std::error::Error>> {
+//         {
+//             #[derive(Debug)]
+//             struct Data<T, S> {
+//                 _x: i32,
+//                 _y: String,
+//                 _v: Vec<T>,
+//                 _s: Vec<S>,
+//             }
+//             let data: Data<i32, &str> = Data {
+//                 _x: 12,
+//                 _y: "hello".to_string(),
+//                 _v: vec![1, 2, 3],
+//                 _s: vec!["macos", "linux", "windows"],
+//             };
+
+//             // define async host function
+//             fn f<T: core::fmt::Debug + Send + Sync + 'static>(
+//                 _frame: CallingFrame,
+//                 _args: Vec<WasmValue>,
+//                 data: *mut std::ffi::c_void,
+//             ) -> Box<(dyn std::future::Future<Output = Result<Vec<WasmValue>, HostFuncError>> + Send)>
+//             {
+//                 let data = unsafe { Box::from_raw(data as *mut T) };
+
+//                 Box::new(async move {
+//                     for _ in 0..10 {
+//                         println!("[async hello] say hello");
+//                         tokio::time::sleep(std::time::Duration::from_secs(1)).await;
+//                         println!("host_data: {:?}", data);
+//                     }
+
+//                     println!("[async hello] Done!");
+
+//                     Ok(vec![])
+//                 })
+//             }
+
+//             // create a FuncType
+//             let result = FuncType::create(vec![], vec![]);
+//             assert!(result.is_ok());
+//             let func_ty = result.unwrap();
+
+//             // create an async host function
+//             let result = Function::create_async_func(
+//                 &func_ty,
+//                 Box::new(f::<Data<i32, &str>>),
+//                 Some(Box::new(data)),
+//                 0,
+//             );
+//             assert!(result.is_ok());
+//             let async_hello_func = result.unwrap();
+
+//             // create an Executor
+//             let result = Executor::create(None, None);
+//             assert!(result.is_ok());
+//             let mut executor = result.unwrap();
+//             assert!(!executor.inner.0.is_null());
+
+//             // create a Store
+//             let result = Store::create();
+//             assert!(result.is_ok());
+//             let mut store = result.unwrap();
+
+//             // create an AsyncWasiModule
+//             let result = AsyncWasiModule::create(Some(vec!["abc"]), Some(vec![("a", "1")]), None);
+//             assert!(result.is_ok());
+//             let async_wasi_module = result.unwrap();
+
+//             // register async_wasi module into the store
+//             let wasi_import = ImportObject::AsyncWasi(async_wasi_module);
+//             let result = executor.register_import_object(&mut store, &wasi_import);
+//             assert!(result.is_ok());
+
+//             // create an ImportModule
+//             let mut import = ImportModule::create::<NeverType>("extern", None)?;
+//             import.add_func("async_hello", async_hello_func);
+
+//             let extern_import = ImportObject::Import(import);
+//             executor.register_import_object(&mut store, &extern_import)?;
+
+//             let extern_instance = store.module("extern")?;
+//             let async_hello = extern_instance.get_func("async_hello")?;
+
+//             async fn tick() {
+//                 let mut i = 0;
+//                 loop {
+//                     println!("[tick] i={i}");
+//                     tokio::time::sleep(std::time::Duration::from_millis(500)).await;
+//                     i += 1;
+//                 }
+//             }
+//             tokio::spawn(tick());
+
+//             let async_state = AsyncState::new();
+//             let _ = executor
+//                 .call_func_async(&async_state, &async_hello, [])
+//                 .await?;
+//         }
+
+//         assert_eq!(ASYNC_HOST_FUNCS.read().len(), 0);
+//         assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 0);
+
+//         Ok(())
+//     }
+// }
diff --git a/crates/wasmedge-sys/src/instance/module.rs b/crates/wasmedge-sys/src/instance/module.rs
index ef0c33da7..aa6a3819e 100644
--- a/crates/wasmedge-sys/src/instance/module.rs
+++ b/crates/wasmedge-sys/src/instance/module.rs
@@ -1,10 +1,7 @@
 //! Defines WasmEdge Instance and other relevant types.
 
 #[cfg(all(feature = "async", target_os = "linux"))]
-use crate::{
-    async_wasi::{wasi_impls, WasiFunc},
-    WasiCtx,
-};
+use crate::r#async::AsyncWasiModule;
 use crate::{
     ffi,
     instance::{function::InnerFunc, global::InnerGlobal, memory::InnerMemory, table::InnerTable},
@@ -12,8 +9,6 @@ use crate::{
     Function, Global, Memory, Table, WasmEdgeResult,
 };
 use parking_lot::Mutex;
-#[cfg(all(feature = "async", target_os = "linux"))]
-use std::path::PathBuf;
 use std::sync::Arc;
 use wasmedge_types::error::{InstanceError, WasmEdgeError};
 
@@ -965,411 +960,6 @@ impl AsImport for WasiModule {
     }
 }
 
-/// A [AsyncWasiModule] is a module instance for the WASI specification and used in the `async` scenario.
-#[cfg(all(feature = "async", target_os = "linux"))]
-#[derive(Debug, Clone)]
-pub struct AsyncWasiModule {
-    pub(crate) inner: Arc<InnerInstance>,
-    pub(crate) registered: bool,
-    name: String,
-    wasi_ctx: Arc<Mutex<WasiCtx>>,
-    funcs: Vec<Function>,
-}
-#[cfg(all(feature = "async", target_os = "linux"))]
-impl Drop for AsyncWasiModule {
-    fn drop(&mut self) {
-        if !self.registered && Arc::strong_count(&self.inner) == 1 && !self.inner.0.is_null() {
-            // free the module instance
-            unsafe {
-                ffi::WasmEdge_ModuleInstanceDelete(self.inner.0);
-            }
-
-            // drop the registered host functions
-            self.funcs.drain(..);
-        }
-    }
-}
-#[cfg(all(feature = "async", target_os = "linux"))]
-impl AsyncWasiModule {
-    pub fn create(
-        args: Option<Vec<&str>>,
-        envs: Option<Vec<(&str, &str)>>,
-        preopens: Option<Vec<(PathBuf, PathBuf)>>,
-    ) -> WasmEdgeResult<Self> {
-        // create wasi context
-        let mut wasi_ctx = WasiCtx::new();
-        if let Some(args) = args {
-            wasi_ctx.push_args(args.iter().map(|x| x.to_string()).collect());
-        }
-        if let Some(envs) = envs {
-            wasi_ctx.push_envs(envs.iter().map(|(k, v)| format!("{}={}", k, v)).collect());
-        }
-        if let Some(preopens) = preopens {
-            for (host_dir, guest_dir) in preopens {
-                wasi_ctx.push_preopen(host_dir, guest_dir)
-            }
-        }
-
-        // create wasi module
-        let name = "wasi_snapshot_preview1";
-        let raw_name = WasmEdgeString::from(name);
-        let ctx = unsafe { ffi::WasmEdge_ModuleInstanceCreate(raw_name.as_raw()) };
-        if ctx.is_null() {
-            return Err(Box::new(WasmEdgeError::Instance(
-                InstanceError::CreateImportModule,
-            )));
-        }
-        let mut async_wasi_module = Self {
-            inner: std::sync::Arc::new(InnerInstance(ctx)),
-            registered: false,
-            name: name.to_string(),
-            wasi_ctx: Arc::new(Mutex::new(wasi_ctx)),
-            funcs: Vec::new(),
-        };
-
-        // add sync/async host functions to the module
-        for wasi_func in wasi_impls() {
-            match wasi_func {
-                WasiFunc::SyncFn(name, (ty_args, ty_rets), real_fn) => {
-                    let func_ty = crate::FuncType::create(ty_args, ty_rets)?;
-                    let func = Function::create_wasi_func(
-                        &func_ty,
-                        real_fn,
-                        Some(&mut async_wasi_module.wasi_ctx.lock()),
-                        0,
-                    )?;
-                    async_wasi_module.add_wasi_func(name, func);
-                }
-                WasiFunc::AsyncFn(name, (ty_args, ty_rets), real_async_fn) => {
-                    let func_ty = crate::FuncType::create(ty_args, ty_rets)?;
-                    let func = Function::create_async_wasi_func(
-                        &func_ty,
-                        real_async_fn,
-                        Some(&mut async_wasi_module.wasi_ctx.lock()),
-                        0,
-                    )?;
-                    async_wasi_module.add_wasi_func(name, func);
-                }
-            }
-        }
-
-        Ok(async_wasi_module)
-    }
-
-    fn add_wasi_func(&mut self, name: impl AsRef<str>, func: Function) {
-        let func_name: WasmEdgeString = name.into();
-        unsafe {
-            ffi::WasmEdge_ModuleInstanceAddFunction(
-                self.inner.0,
-                func_name.as_raw(),
-                func.inner.lock().0,
-            );
-        }
-
-        func.inner.lock().0 = std::ptr::null_mut();
-    }
-
-    pub fn init_wasi(
-        &mut self,
-        args: Option<Vec<&str>>,
-        envs: Option<Vec<(&str, &str)>>,
-        preopens: Option<Vec<(PathBuf, PathBuf)>>,
-    ) -> WasmEdgeResult<()> {
-        // create wasi context
-        let mut wasi_ctx = WasiCtx::new();
-        if let Some(args) = args {
-            wasi_ctx.push_args(args.iter().map(|x| x.to_string()).collect());
-        }
-        if let Some(envs) = envs {
-            wasi_ctx.push_envs(envs.iter().map(|(k, v)| format!("{}={}", k, v)).collect());
-        }
-        if let Some(preopens) = preopens {
-            for (host_dir, guest_dir) in preopens {
-                wasi_ctx.push_preopen(host_dir, guest_dir)
-            }
-        }
-
-        self.wasi_ctx = Arc::new(Mutex::new(wasi_ctx));
-
-        // add sync/async host functions to the module
-        for wasi_func in wasi_impls() {
-            match wasi_func {
-                WasiFunc::SyncFn(name, (ty_args, ty_rets), real_fn) => {
-                    let func_ty = crate::FuncType::create(ty_args, ty_rets)?;
-                    let func = Function::create_wasi_func(
-                        &func_ty,
-                        real_fn,
-                        Some(&mut self.wasi_ctx.lock()),
-                        0,
-                    )?;
-                    self.add_wasi_func(name, func);
-                }
-                WasiFunc::AsyncFn(name, (ty_args, ty_rets), real_async_fn) => {
-                    let func_ty = crate::FuncType::create(ty_args, ty_rets)?;
-                    let func = Function::create_async_wasi_func(
-                        &func_ty,
-                        real_async_fn,
-                        Some(&mut self.wasi_ctx.lock()),
-                        0,
-                    )?;
-                    self.add_wasi_func(name, func);
-                }
-            }
-        }
-
-        Ok(())
-    }
-
-    /// Returns the WASI exit code.
-    ///
-    /// The WASI exit code can be accessed after running the "_start" function of a `wasm32-wasi` program.
-    pub fn exit_code(&self) -> u32 {
-        self.wasi_ctx.lock().exit_code
-    }
-}
-#[cfg(all(feature = "async", target_os = "linux"))]
-impl AsInstance for AsyncWasiModule {
-    fn get_func(&self, name: impl AsRef<str>) -> WasmEdgeResult<Function> {
-        let func_name: WasmEdgeString = name.as_ref().into();
-        let func_ctx = unsafe {
-            ffi::WasmEdge_ModuleInstanceFindFunction(self.inner.0 as *const _, func_name.as_raw())
-        };
-        match func_ctx.is_null() {
-            true => Err(Box::new(WasmEdgeError::Instance(
-                InstanceError::NotFoundFunc(name.as_ref().to_string()),
-            ))),
-            false => Ok(Function {
-                inner: Arc::new(Mutex::new(InnerFunc(func_ctx))),
-                registered: true,
-            }),
-        }
-    }
-
-    fn get_table(&self, name: impl AsRef<str>) -> WasmEdgeResult<Table> {
-        let table_name: WasmEdgeString = name.as_ref().into();
-        let ctx = unsafe {
-            ffi::WasmEdge_ModuleInstanceFindTable(self.inner.0 as *const _, table_name.as_raw())
-        };
-        match ctx.is_null() {
-            true => Err(Box::new(WasmEdgeError::Instance(
-                InstanceError::NotFoundTable(name.as_ref().to_string()),
-            ))),
-            false => Ok(Table {
-                inner: Arc::new(Mutex::new(InnerTable(ctx))),
-                registered: true,
-            }),
-        }
-    }
-
-    fn get_memory(&self, name: impl AsRef<str>) -> WasmEdgeResult<Memory> {
-        let mem_name: WasmEdgeString = name.as_ref().into();
-        let ctx = unsafe {
-            ffi::WasmEdge_ModuleInstanceFindMemory(self.inner.0 as *const _, mem_name.as_raw())
-        };
-        match ctx.is_null() {
-            true => Err(Box::new(WasmEdgeError::Instance(
-                InstanceError::NotFoundMem(name.as_ref().to_string()),
-            ))),
-            false => Ok(Memory {
-                inner: Arc::new(Mutex::new(InnerMemory(ctx))),
-                registered: true,
-            }),
-        }
-    }
-
-    fn get_global(&self, name: impl AsRef<str>) -> WasmEdgeResult<Global> {
-        let global_name: WasmEdgeString = name.as_ref().into();
-        let ctx = unsafe {
-            ffi::WasmEdge_ModuleInstanceFindGlobal(self.inner.0 as *const _, global_name.as_raw())
-        };
-        match ctx.is_null() {
-            true => Err(Box::new(WasmEdgeError::Instance(
-                InstanceError::NotFoundGlobal(name.as_ref().to_string()),
-            ))),
-            false => Ok(Global {
-                inner: Arc::new(Mutex::new(InnerGlobal(ctx))),
-                registered: true,
-            }),
-        }
-    }
-
-    /// Returns the length of the exported [function instances](crate::Function) in this module instance.
-    fn func_len(&self) -> u32 {
-        unsafe { ffi::WasmEdge_ModuleInstanceListFunctionLength(self.inner.0) }
-    }
-
-    /// Returns the names of the exported [function instances](crate::Function) in this module instance.
-    fn func_names(&self) -> Option<Vec<String>> {
-        let len_func_names = self.func_len();
-        match len_func_names > 0 {
-            true => {
-                let mut func_names = Vec::with_capacity(len_func_names as usize);
-                unsafe {
-                    ffi::WasmEdge_ModuleInstanceListFunction(
-                        self.inner.0,
-                        func_names.as_mut_ptr(),
-                        len_func_names,
-                    );
-                    func_names.set_len(len_func_names as usize);
-                }
-
-                let names = func_names
-                    .into_iter()
-                    .map(|x| x.into())
-                    .collect::<Vec<String>>();
-                Some(names)
-            }
-            false => None,
-        }
-    }
-
-    /// Returns the length of the exported [table instances](crate::Table) in this module instance.
-    fn table_len(&self) -> u32 {
-        unsafe { ffi::WasmEdge_ModuleInstanceListTableLength(self.inner.0) }
-    }
-
-    /// Returns the names of the exported [table instances](crate::Table) in this module instance.
-    fn table_names(&self) -> Option<Vec<String>> {
-        let len_table_names = self.table_len();
-        match len_table_names > 0 {
-            true => {
-                let mut table_names = Vec::with_capacity(len_table_names as usize);
-                unsafe {
-                    ffi::WasmEdge_ModuleInstanceListTable(
-                        self.inner.0,
-                        table_names.as_mut_ptr(),
-                        len_table_names,
-                    );
-                    table_names.set_len(len_table_names as usize);
-                }
-
-                let names = table_names
-                    .into_iter()
-                    .map(|x| x.into())
-                    .collect::<Vec<String>>();
-                Some(names)
-            }
-            false => None,
-        }
-    }
-
-    /// Returns the length of the exported [memory instances](crate::Memory) in this module instance.
-    fn mem_len(&self) -> u32 {
-        unsafe { ffi::WasmEdge_ModuleInstanceListMemoryLength(self.inner.0) }
-    }
-
-    /// Returns the names of all exported [memory instances](crate::Memory) in this module instance.
-    fn mem_names(&self) -> Option<Vec<String>> {
-        let len_mem_names = self.mem_len();
-        match len_mem_names > 0 {
-            true => {
-                let mut mem_names = Vec::with_capacity(len_mem_names as usize);
-                unsafe {
-                    ffi::WasmEdge_ModuleInstanceListMemory(
-                        self.inner.0,
-                        mem_names.as_mut_ptr(),
-                        len_mem_names,
-                    );
-                    mem_names.set_len(len_mem_names as usize);
-                }
-
-                let names = mem_names
-                    .into_iter()
-                    .map(|x| x.into())
-                    .collect::<Vec<String>>();
-                Some(names)
-            }
-            false => None,
-        }
-    }
-
-    /// Returns the length of the exported [global instances](crate::Global) in this module instance.
-    fn global_len(&self) -> u32 {
-        unsafe { ffi::WasmEdge_ModuleInstanceListGlobalLength(self.inner.0) }
-    }
-
-    /// Returns the names of the exported [global instances](crate::Global) in this module instance.
-    fn global_names(&self) -> Option<Vec<String>> {
-        let len_global_names = self.global_len();
-        match len_global_names > 0 {
-            true => {
-                let mut global_names = Vec::with_capacity(len_global_names as usize);
-                unsafe {
-                    ffi::WasmEdge_ModuleInstanceListGlobal(
-                        self.inner.0,
-                        global_names.as_mut_ptr(),
-                        len_global_names,
-                    );
-                    global_names.set_len(len_global_names as usize);
-                }
-
-                let names = global_names
-                    .into_iter()
-                    .map(|x| x.into())
-                    .collect::<Vec<String>>();
-                Some(names)
-            }
-            false => None,
-        }
-    }
-}
-#[cfg(all(feature = "async", target_os = "linux"))]
-impl AsImport for AsyncWasiModule {
-    fn name(&self) -> &str {
-        self.name.as_str()
-    }
-
-    fn add_func(&mut self, name: impl AsRef<str>, func: Function) {
-        self.funcs.push(func);
-        let f = self.funcs.last_mut().unwrap();
-
-        let func_name: WasmEdgeString = name.into();
-        unsafe {
-            ffi::WasmEdge_ModuleInstanceAddFunction(
-                self.inner.0,
-                func_name.as_raw(),
-                f.inner.lock().0,
-            );
-        }
-    }
-
-    fn add_table(&mut self, name: impl AsRef<str>, table: Table) {
-        let table_name: WasmEdgeString = name.as_ref().into();
-        unsafe {
-            ffi::WasmEdge_ModuleInstanceAddTable(
-                self.inner.0,
-                table_name.as_raw(),
-                table.inner.lock().0,
-            );
-        }
-        table.inner.lock().0 = std::ptr::null_mut();
-    }
-
-    fn add_memory(&mut self, name: impl AsRef<str>, memory: Memory) {
-        let mem_name: WasmEdgeString = name.as_ref().into();
-        unsafe {
-            ffi::WasmEdge_ModuleInstanceAddMemory(
-                self.inner.0,
-                mem_name.as_raw(),
-                memory.inner.lock().0,
-            );
-        }
-        memory.inner.lock().0 = std::ptr::null_mut();
-    }
-
-    fn add_global(&mut self, name: impl AsRef<str>, global: Global) {
-        let global_name: WasmEdgeString = name.as_ref().into();
-        unsafe {
-            ffi::WasmEdge_ModuleInstanceAddGlobal(
-                self.inner.0,
-                global_name.as_raw(),
-                global.inner.lock().0,
-            );
-        }
-        global.inner.lock().0 = std::ptr::null_mut();
-    }
-}
-
 /// The object to be registered via the the [Executor::register_import_object](crate::Executor::register_import_object) function is required to implement this trait.
 pub trait AsImport {
     /// Returns the name of the module instance.
diff --git a/crates/wasmedge-sys/src/lib.rs b/crates/wasmedge-sys/src/lib.rs
index aecdad858..5ff921728 100644
--- a/crates/wasmedge-sys/src/lib.rs
+++ b/crates/wasmedge-sys/src/lib.rs
@@ -61,9 +61,6 @@ pub mod ast_module;
 #[cfg(all(feature = "async", target_os = "linux"))]
 pub mod r#async;
 #[doc(hidden)]
-#[cfg(all(feature = "async", target_os = "linux"))]
-pub mod async_wasi;
-#[doc(hidden)]
 #[cfg(feature = "aot")]
 pub mod compiler;
 #[doc(hidden)]
@@ -101,9 +98,6 @@ pub use frame::CallingFrame;
 #[cfg(not(feature = "async"))]
 #[doc(inline)]
 pub use instance::module::WasiModule;
-#[cfg(all(feature = "async", target_os = "linux"))]
-#[doc(inline)]
-pub use instance::{function::AsyncHostFn, module::AsyncWasiModule};
 #[doc(inline)]
 pub use instance::{
     function::{FuncRef, FuncType, Function},
diff --git a/crates/wasmedge-sys/src/plugin.rs b/crates/wasmedge-sys/src/plugin.rs
index 1d4e0083a..fd0b5bc48 100644
--- a/crates/wasmedge-sys/src/plugin.rs
+++ b/crates/wasmedge-sys/src/plugin.rs
@@ -596,6 +596,7 @@ mod tests {
         not(feature = "static")
     ))]
     #[test]
+    #[ignore]
     fn test_plugin_wasmedge_process() {
         use super::*;
 
diff --git a/crates/wasmedge-types/Cargo.toml b/crates/wasmedge-types/Cargo.toml
index d137828bc..21da7e9f3 100644
--- a/crates/wasmedge-types/Cargo.toml
+++ b/crates/wasmedge-types/Cargo.toml
@@ -7,7 +7,7 @@ license = "Apache-2.0"
 name = "wasmedge-types"
 readme = "README.md"
 repository = "https://github.com/WasmEdge/wasmedge-rust-sdk"
-version = "0.4.2"
+version = "0.4.3"
 
 [dependencies]
 thiserror = "1.0.30"
diff --git a/crates/wasmedge-types/src/error.rs b/crates/wasmedge-types/src/error.rs
index fb8dd447f..5f72f26ec 100644
--- a/crates/wasmedge-types/src/error.rs
+++ b/crates/wasmedge-types/src/error.rs
@@ -225,6 +225,8 @@ pub enum StoreError {
 pub enum VmError {
     #[error("Fail to create Vm context")]
     Create,
+    #[error("Fail to create Vm context. It is required to provide a `WasiContext` instance for creating a Vm when the `wasi` config option is enabled.")]
+    CreateWithWasiContext,
     #[error("Fail to get the type of the target function ({0})")]
     NotFoundFuncType(String),
     #[error("Fail to get module instance ({0})")]
diff --git a/examples/wasmedge-sys/async_hello.rs b/examples/wasmedge-sys/async_hello.rs
index 37f2dc432..6f89d585a 100644
--- a/examples/wasmedge-sys/async_hello.rs
+++ b/examples/wasmedge-sys/async_hello.rs
@@ -1,6 +1,13 @@
 // rustup target add wasm32-wasi
 // rustc async_hello.rs --target=wasm32-wasi -o async_hello.wasm
 fn main() {
+    for arg in std::env::args() {
+        println!("[wasm-app] arg: {}", arg);
+    }
+
+    let val = std::env::var("ENV").expect("failed to get environment variable: ENV");
+    println!("[wasm-app] ENV={val}");
+
     for _ in 0..10 {
         println!("[async hello] say hello");
         std::thread::sleep(std::time::Duration::from_secs(1));
diff --git a/examples/wasmedge-sys/async_hello.wasm b/examples/wasmedge-sys/async_hello.wasm
deleted file mode 100755
index 86f6bd0b7..000000000
Binary files a/examples/wasmedge-sys/async_hello.wasm and /dev/null differ
diff --git a/examples/wasmedge-sys/async_host_func.rs b/examples/wasmedge-sys/async_host_func.rs
index 92b635275..4576ec721 100644
--- a/examples/wasmedge-sys/async_host_func.rs
+++ b/examples/wasmedge-sys/async_host_func.rs
@@ -7,7 +7,9 @@
 //! ```
 
 #[cfg(feature = "async")]
-use wasmedge_sys::{r#async::AsyncState, CallingFrame, Executor, FuncType, Function, WasmValue};
+use wasmedge_sys::{
+    r#async::fiber::AsyncState, CallingFrame, Executor, FuncType, Function, WasmValue,
+};
 #[cfg(feature = "async")]
 use wasmedge_types::error::HostFuncError;
 
diff --git a/examples/wasmedge-sys/async_run_func.rs b/examples/wasmedge-sys/async_run_func.rs
index 9915adfb8..1794bdc3a 100644
--- a/examples/wasmedge-sys/async_run_func.rs
+++ b/examples/wasmedge-sys/async_run_func.rs
@@ -9,7 +9,9 @@
 //! ```
 
 #[cfg(all(feature = "async", target_os = "linux"))]
-use wasmedge_sys::{r#async::AsyncState, Config, Executor, Loader, Store, Validator, WasmValue};
+use wasmedge_sys::{
+    r#async::fiber::AsyncState, Config, Executor, Loader, Store, Validator, WasmValue,
+};
 #[cfg(all(feature = "async", target_os = "linux"))]
 use wasmedge_types::wat2wasm;
 
diff --git a/examples/wasmedge-sys/async_run_registered_func.rs b/examples/wasmedge-sys/async_run_registered_func.rs
index 5c05ef90d..0d2547504 100644
--- a/examples/wasmedge-sys/async_run_registered_func.rs
+++ b/examples/wasmedge-sys/async_run_registered_func.rs
@@ -9,7 +9,9 @@
 //! ```
 
 #[cfg(all(feature = "async", target_os = "linux"))]
-use wasmedge_sys::{r#async::AsyncState, Config, Executor, Loader, Store, Validator, WasmValue};
+use wasmedge_sys::{
+    r#async::fiber::AsyncState, Config, Executor, Loader, Store, Validator, WasmValue,
+};
 #[cfg(all(feature = "async", target_os = "linux"))]
 use wasmedge_types::wat2wasm;
 
diff --git a/examples/wasmedge-sys/context_data_to_host_func.rs b/examples/wasmedge-sys/context_data_to_host_func.rs
index 936c1943c..1b466134e 100644
--- a/examples/wasmedge-sys/context_data_to_host_func.rs
+++ b/examples/wasmedge-sys/context_data_to_host_func.rs
@@ -1,4 +1,3 @@
-use wasmedge_macro::sys_host_function;
 use wasmedge_sys::{CallingFrame, Executor, FuncType, Function, WasmValue};
 use wasmedge_types::{error::HostFuncError, ValType};
 
@@ -10,15 +9,15 @@ struct Data<T, S> {
     _s: Vec<S>,
 }
 
-#[sys_host_function]
 fn real_add<T: core::fmt::Debug>(
     _frame: CallingFrame,
     input: Vec<WasmValue>,
-    data: &mut Data<i32, &str>,
+    data: *mut std::ffi::c_void,
 ) -> Result<Vec<WasmValue>, HostFuncError> {
     println!("Rust: Entering Rust function real_add");
 
-    println!("data: {data:?}");
+    let host_data = unsafe { Box::from_raw(data as *mut T) };
+    println!("host_data: {:?}", host_data);
 
     if input.len() != 2 {
         return Err(HostFuncError::User(1));
@@ -44,7 +43,7 @@ fn real_add<T: core::fmt::Debug>(
 }
 
 fn main() -> Result<(), Box<dyn std::error::Error>> {
-    let mut data: Data<i32, &str> = Data {
+    let data: Data<i32, &str> = Data {
         _x: 12,
         _y: "hello".to_string(),
         _v: vec![1, 2, 3],
@@ -56,7 +55,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
     assert!(result.is_ok());
     let func_ty = result.unwrap();
     // create a host function
-    let result = Function::create_sync_func(&func_ty, Box::new(real_add), Some(&mut data), 0);
+    let result = Function::create_sync_func(
+        &func_ty,
+        Box::new(real_add::<Data<i32, &str>>),
+        Some(Box::new(data)),
+        0,
+    );
     assert!(result.is_ok());
     let host_func = result.unwrap();
 
diff --git a/examples/wasmedge-sys/hello.rs b/examples/wasmedge-sys/hello.rs
new file mode 100644
index 000000000..1f7ad4725
--- /dev/null
+++ b/examples/wasmedge-sys/hello.rs
@@ -0,0 +1,12 @@
+// rustup target add wasm32-wasi
+// rustc hello.rs --target=wasm32-wasi -o hello.wasm
+fn main() {
+    for arg in std::env::args() {
+        println!("[hello] arg: {}", arg);
+    }
+
+    let val = std::env::var("ENV").expect("failed to get environment variable: ENV");
+    println!("[hello] ENV={val}");
+
+    println!("[hello] Done!");
+}
diff --git a/src/async.rs b/src/async.rs
new file mode 100644
index 000000000..9ac12ed10
--- /dev/null
+++ b/src/async.rs
@@ -0,0 +1,46 @@
+/// The state of an asynchronous task.
+pub type AsyncState = wasmedge_sys::r#async::fiber::AsyncState;
+
+/// Represents a wasi module instance.
+#[derive(Debug, Clone)]
+pub(crate) struct WasiInstance(pub(crate) wasmedge_sys::r#async::AsyncWasiModule);
+
+#[derive(Debug)]
+pub struct WasiContext {
+    pub(crate) inner: async_wasi::WasiCtx,
+}
+impl WasiContext {
+    pub fn new(
+        args: Option<Vec<&str>>,
+        envs: Option<Vec<(&str, &str)>>,
+        preopens: Option<Vec<(&str, &str)>>,
+    ) -> Self {
+        let mut inner = async_wasi::WasiCtx::new();
+
+        if let Some(args) = args {
+            inner.push_args(args.iter().map(|x| x.to_string()).collect());
+        }
+        if let Some(envs) = envs {
+            inner.push_envs(envs.iter().map(|(k, v)| format!("{}={}", k, v)).collect());
+        }
+        if let Some(preopens) = preopens {
+            for (host_dir, guest_dir) in preopens {
+                inner.push_preopen(
+                    std::path::PathBuf::from(host_dir),
+                    std::path::PathBuf::from(guest_dir),
+                )
+            }
+        }
+
+        Self { inner }
+    }
+
+    pub fn exit_code(&self) -> u32 {
+        self.inner.exit_code
+    }
+}
+impl Default for WasiContext {
+    fn default() -> Self {
+        Self::new(None, None, None)
+    }
+}
diff --git a/src/externals/function.rs b/src/externals/function.rs
index 00f2b7d76..730076205 100644
--- a/src/externals/function.rs
+++ b/src/externals/function.rs
@@ -44,7 +44,7 @@ impl Func {
             + Send
             + Sync
             + 'static,
-        data: Option<&mut T>,
+        data: Option<Box<T>>,
     ) -> WasmEdgeResult<Self> {
         let boxed_func = Box::new(real_func);
         let inner = sys::Function::create_sync_func::<T>(&ty.clone().into(), boxed_func, data, 0)?;
@@ -78,7 +78,7 @@ impl Func {
             + Send
             + Sync
             + 'static,
-        data: Option<&mut T>,
+        data: Option<Box<T>>,
     ) -> WasmEdgeResult<Self>
     where
         Args: WasmValTypeList,
@@ -499,6 +499,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg(not(feature = "async"))]
     fn test_func_wrap_closure() -> Result<(), Box<dyn std::error::Error>> {
         // define a closure
         let real_add = |_: CallingFrame,
@@ -557,6 +558,8 @@ mod tests {
     #[cfg(all(feature = "async", target_os = "linux"))]
     #[tokio::test]
     async fn test_func_wrap_async_closure() -> Result<(), Box<dyn std::error::Error>> {
+        use crate::r#async::WasiContext;
+
         // define an async closure
         let c = |_frame: CallingFrame,
                  _args: Vec<WasmValue>,
@@ -600,8 +603,11 @@ mod tests {
         assert!(result.is_ok());
         let import = result.unwrap();
 
+        // create a default WasiContext instance
+        let wasi_ctx = WasiContext::default();
+
         // create a Vm context
-        let result = VmBuilder::new().build();
+        let result = VmBuilder::new().with_wasi_context(wasi_ctx).build();
         assert!(result.is_ok());
         let vm = result.unwrap();
 
diff --git a/src/import.rs b/src/import.rs
index 5000b141f..f75746d04 100644
--- a/src/import.rs
+++ b/src/import.rs
@@ -54,7 +54,7 @@ impl ImportObjectBuilder {
             + Send
             + Sync
             + 'static,
-        data: Option<&mut D>,
+        data: Option<Box<D>>,
     ) -> WasmEdgeResult<Self>
     where
         Args: WasmValTypeList,
@@ -98,7 +98,7 @@ impl ImportObjectBuilder {
             + Send
             + Sync
             + 'static,
-        data: Option<&mut D>,
+        data: Option<Box<D>>,
     ) -> WasmEdgeResult<Self> {
         let boxed_func = Box::new(real_func);
         let inner_func = sys::Function::create_sync_func::<D>(&ty.into(), boxed_func, data, 0)?;
@@ -262,13 +262,15 @@ impl ImportObject {
 #[cfg(test)]
 mod tests {
     use super::*;
+    #[cfg(not(feature = "async"))]
+    use crate::VmBuilder;
     use crate::{
         config::{CommonConfigOptions, ConfigBuilder},
         error::{GlobalError, HostFuncError, WasmEdgeError},
         params,
         types::Val,
         CallingFrame, Executor, Global, GlobalType, Memory, MemoryType, Mutability, NeverType,
-        RefType, Statistics, Store, Table, TableType, ValType, VmBuilder, WasmVal, WasmValue,
+        RefType, Statistics, Store, Table, TableType, ValType, WasmVal, WasmValue,
     };
     use std::{
         sync::{Arc, Mutex},
@@ -285,6 +287,7 @@ mod tests {
     }
 
     #[test]
+    #[cfg(not(feature = "async"))]
     #[allow(clippy::assertions_on_result_states)]
     fn test_import_builder_with_data() {
         // define host data
diff --git a/src/lib.rs b/src/lib.rs
index 6ba772d17..d09cb901d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -60,6 +60,8 @@
 //! This project is licensed under the terms of the [Apache 2.0 license](https://github.com/tensorflow/rust/blob/HEAD/LICENSE).
 //!
 
+#[cfg(all(feature = "async", target_os = "linux"))]
+pub mod r#async;
 #[doc(hidden)]
 pub mod caller;
 #[doc(hidden)]
@@ -130,21 +132,6 @@ pub type NeverType = wasmedge_types::NeverType;
 #[doc(hidden)]
 pub type CallingFrame = wasmedge_sys::CallingFrame;
 
-/// Defines the signature of a host function.
-#[cfg(all(feature = "async", target_os = "linux"))]
-pub type HostFn<T> = wasmedge_sys::instance::function::HostFn<T>;
-
-/// Defines the types used in the `async` scenarios.
-#[cfg(all(feature = "async", target_os = "linux"))]
-pub mod r#async {
-    /// The state of an asynchronous task.
-    pub type AsyncState = wasmedge_sys::r#async::AsyncState;
-    /// Defines the signature of an asynchronous host function.
-    pub type AsyncHostFn<T> = wasmedge_sys::AsyncHostFn<T>;
-    /// Type of wasi context that is used to configure the wasi environment.
-    pub type WasiCtx = wasmedge_sys::WasiCtx;
-}
-
 /// The object that is used to perform a [host function](crate::Func) is required to implement this trait.
 pub trait Engine {
     /// Runs a host function instance and returns the results.
diff --git a/src/plugin.rs b/src/plugin.rs
index f38ba5d73..1d92157e4 100644
--- a/src/plugin.rs
+++ b/src/plugin.rs
@@ -268,7 +268,7 @@ impl<T: Send + Sync + Clone> PluginModuleBuilder<T> {
             + Send
             + Sync
             + 'static,
-        data: Option<&mut D>,
+        data: Option<Box<D>>,
     ) -> WasmEdgeResult<Self>
     where
         Args: WasmValTypeList,
diff --git a/src/vm.rs b/src/vm.rs
index 70eb7e287..c82efb9ec 100644
--- a/src/vm.rs
+++ b/src/vm.rs
@@ -1,11 +1,12 @@
 //! Defines WasmEdge Vm struct.
 
 #[cfg(all(feature = "async", target_os = "linux"))]
-use crate::r#async::AsyncState;
+use crate::r#async::{AsyncState, WasiContext, WasiInstance};
+#[cfg(not(feature = "async"))]
+use crate::wasi::WasiInstance;
 use crate::{
     config::Config,
     error::{VmError, WasmEdgeError},
-    wasi::WasiInstance,
     Executor, HostRegistration, ImportObject, Instance, Module, Statistics, Store, WasmEdgeResult,
     WasmValue,
 };
@@ -19,6 +20,8 @@ pub struct VmBuilder {
     stat: Option<Statistics>,
     store: Option<Store>,
     plugins: Vec<(String, String)>,
+    #[cfg(all(feature = "async", target_os = "linux"))]
+    wasi_ctx: Option<WasiContext>,
 }
 impl VmBuilder {
     /// Creates a new [VmBuilder].
@@ -162,6 +165,13 @@ impl VmBuilder {
         Ok(vm)
     }
 
+    #[cfg(all(feature = "async", target_os = "linux"))]
+    /// Sets the [WasiContext] for the [Vm] to build.
+    pub fn with_wasi_context(mut self, wasi_ctx: WasiContext) -> Self {
+        self.wasi_ctx = Some(wasi_ctx);
+        self
+    }
+
     /// Creates a new [Vm].
     ///
     /// # Error
@@ -191,21 +201,31 @@ impl VmBuilder {
             plugin_host_instances: Vec::new(),
         };
 
-        // * built-in host instances
+        // * register AsyncWasiModule
         if let Some(cfg) = vm.config.as_ref() {
             if cfg.wasi_enabled() {
-                if let Ok(wasi_module) = sys::AsyncWasiModule::create(None, None, None) {
-                    vm.executor.inner.register_import_object(
-                        &vm.store.inner,
-                        &sys::ImportObject::AsyncWasi(wasi_module.clone()),
-                    )?;
+                match self.wasi_ctx {
+                    Some(ctx) => {
+                        // create an AsyncWasiModule instance
+                        let wasi_module =
+                            sys::r#async::module::AsyncWasiModule::create_from_wasi_context(
+                                ctx.inner,
+                            )?;
+
+                        // register the AsyncWasiModule instance
+                        vm.executor.inner.register_import_object(
+                            &vm.store.inner,
+                            &sys::ImportObject::AsyncWasi(wasi_module.clone()),
+                        )?;
 
-                    vm.builtin_host_instances.insert(
-                        HostRegistration::Wasi,
-                        HostRegistrationInstance::Wasi(WasiInstance { inner: wasi_module }),
-                    );
-                } else {
-                    panic!("failed to create AsyncWasiModule which is only available on Linux")
+                        vm.builtin_host_instances.insert(
+                            HostRegistration::Wasi,
+                            HostRegistrationInstance::Wasi(WasiInstance(wasi_module)),
+                        );
+                    }
+                    None => {
+                        return Err(Box::new(WasmEdgeError::Vm(VmError::CreateWithWasiContext)));
+                    }
                 }
             }
         }
@@ -746,7 +766,7 @@ impl Vm {
     ///
     /// To retrieve  the [wasi module instance], a [config](crate::config::Config) with the enabled [wasi](crate::config::HostRegistrationConfigOptions::wasi) option should be given when create this vm.
     ///
-
+    #[cfg(not(feature = "async"))]
     pub fn wasi_module(&self) -> Option<&WasiInstance> {
         match self.builtin_host_instances.get(&HostRegistration::Wasi) {
             Some(HostRegistrationInstance::Wasi(wasi_instance)) => Some(wasi_instance),
@@ -758,7 +778,7 @@ impl Vm {
     ///
     /// To retrieve the [wasi module instance], a [config](crate::config::Config) with the enabled [wasi](crate::config::HostRegistrationConfigOptions::wasi) option should be given when create this vm.
     ///
-
+    #[cfg(not(feature = "async"))]
     pub fn wasi_module_mut(&mut self) -> Option<&mut WasiInstance> {
         match self.builtin_host_instances.get_mut(&HostRegistration::Wasi) {
             Some(HostRegistrationInstance::Wasi(wasi_instance)) => Some(wasi_instance),
@@ -845,7 +865,7 @@ impl Vm {
 
 #[derive(Debug, Clone)]
 enum HostRegistrationInstance {
-    Wasi(crate::wasi::WasiInstance),
+    Wasi(WasiInstance),
 }
 
 #[cfg(not(feature = "async"))]
diff --git a/src/wasi.rs b/src/wasi.rs
index a6b553c45..769bea6fe 100644
--- a/src/wasi.rs
+++ b/src/wasi.rs
@@ -1,16 +1,20 @@
 //! Defines wasi module instance types, including WasiInstance, WasiNnInstance, wasi-crypto instances.
 
-use crate::{
-    AsInstance, Func, FuncType, Global, GlobalType, Memory, MemoryType, Table, TableType,
-    WasmEdgeResult,
-};
-use wasmedge_sys::{self as sys, AsImport, AsInstance as sys_as_instance_trait};
+cfg_if::cfg_if! {
+    if #[cfg(not(feature = "async"))] {
+        use crate::{
+            AsInstance, Func, FuncType, Global, GlobalType, Memory, MemoryType, Table, TableType,
+            WasmEdgeResult,
+        };
+        use wasmedge_sys::{AsImport, AsInstance as sys_as_instance_trait};
+    }
+}
 
 /// Represents a wasi module instance.
 #[cfg(not(feature = "async"))]
 #[derive(Debug, Clone)]
 pub struct WasiInstance {
-    pub(crate) inner: sys::WasiModule,
+    pub(crate) inner: wasmedge_sys::WasiModule,
 }
 #[cfg(not(feature = "async"))]
 impl WasiInstance {
@@ -169,138 +173,3 @@ impl AsInstance for WasiInstance {
         })
     }
 }
-
-/// Represents a wasi module instance.
-#[cfg(all(feature = "async", target_os = "linux"))]
-#[derive(Debug, Clone)]
-pub struct WasiInstance {
-    pub(crate) inner: sys::AsyncWasiModule,
-}
-#[cfg(all(feature = "async", target_os = "linux"))]
-impl WasiInstance {
-    /// Initializes the WASI host module with the given parameters.
-    ///
-    /// # Arguments
-    ///
-    /// * `args` - The commandline arguments. Note that the first argument is the program name.
-    ///
-    /// * `envs` - The environment variables.
-    ///
-    /// * `preopens` - The directories to pre-open.
-    ///
-    /// # Example
-    ///
-    /// ```ignore
-    /// let wasi_module = vm.wasi_module_mut().ok_or("failed to get wasi module")?;
-    /// wasi_module.initialize(
-    ///     None,
-    ///     Some(vec![("ENV", "VAL")]),
-    ///     Some(vec![(
-    ///         std::path::PathBuf::from("."),
-    ///         std::path::PathBuf::from("."),
-    ///     )]),
-    /// )?;
-    /// ```
-    ///
-    pub fn initialize(
-        &mut self,
-        args: Option<Vec<&str>>,
-        envs: Option<Vec<(&str, &str)>>,
-        preopens: Option<Vec<(std::path::PathBuf, std::path::PathBuf)>>,
-    ) -> WasmEdgeResult<()> {
-        self.inner.init_wasi(args, envs, preopens)
-    }
-
-    /// Returns the WASI exit code.
-    ///
-    /// The WASI exit code can be accessed after running the "_start" function of a `wasm32-wasi` program.
-    pub fn exit_code(&self) -> u32 {
-        self.inner.exit_code()
-    }
-}
-#[cfg(all(feature = "async", target_os = "linux"))]
-impl AsInstance for WasiInstance {
-    fn name(&self) -> &str {
-        self.inner.name()
-    }
-
-    fn func_count(&self) -> usize {
-        self.inner.func_len() as usize
-    }
-
-    fn func_names(&self) -> Option<Vec<String>> {
-        self.inner.func_names()
-    }
-
-    fn func(&self, name: impl AsRef<str>) -> WasmEdgeResult<Func> {
-        let inner_func = self.inner.get_func(name.as_ref())?;
-        let ty: FuncType = inner_func.ty()?.into();
-
-        Ok(Func {
-            inner: inner_func,
-            name: Some(name.as_ref().into()),
-            mod_name: None,
-            ty,
-        })
-    }
-
-    fn global_count(&self) -> usize {
-        self.inner.global_len() as usize
-    }
-
-    fn global_names(&self) -> Option<Vec<String>> {
-        self.inner.global_names()
-    }
-
-    fn global(&self, name: impl AsRef<str>) -> WasmEdgeResult<Global> {
-        let inner_global = self.inner.get_global(name.as_ref())?;
-        let ty: GlobalType = inner_global.ty()?.into();
-
-        Ok(Global {
-            inner: inner_global,
-            name: Some(name.as_ref().into()),
-            mod_name: None,
-            ty,
-        })
-    }
-
-    fn memory_count(&self) -> usize {
-        self.inner.mem_len() as usize
-    }
-
-    fn memory_names(&self) -> Option<Vec<String>> {
-        self.inner.mem_names()
-    }
-
-    fn memory(&self, name: impl AsRef<str>) -> WasmEdgeResult<Memory> {
-        let inner_memory = self.inner.get_memory(name.as_ref())?;
-        let ty: MemoryType = inner_memory.ty()?.into();
-
-        Ok(Memory {
-            inner: inner_memory,
-            name: Some(name.as_ref().into()),
-            mod_name: None,
-            ty,
-        })
-    }
-
-    fn table_count(&self) -> usize {
-        self.inner.table_len() as usize
-    }
-
-    fn table_names(&self) -> Option<Vec<String>> {
-        self.inner.table_names()
-    }
-
-    fn table(&self, name: impl AsRef<str>) -> WasmEdgeResult<Table> {
-        let inner_table = self.inner.get_table(name.as_ref())?;
-        let ty: TableType = inner_table.ty()?.into();
-
-        Ok(Table {
-            inner: inner_table,
-            name: Some(name.as_ref().into()),
-            mod_name: None,
-            ty,
-        })
-    }
-}


Test patch: