Skip to content

Commit

Permalink
[feat] Support new c-apis (#13)
Browse files Browse the repository at this point in the history
* feat(rust-sys): implement `create_with_data` and `host_data` to support new c-apis

Signed-off-by: Xin Liu <[email protected]>

* chore(rust-sys): export Finalizer type

Signed-off-by: Xin Liu <[email protected]>

* feat(rust-sdk): implement `host_data` in Instance

Signed-off-by: Xin Liu <[email protected]>

* feat(rust-sdk): implement `build_with_data` in ImportObjectBuilder

Signed-off-by: Xin Liu <[email protected]>

* chore(rust-sdk): export Finalizer type

Signed-off-by: Xin Liu <[email protected]>

* chore(rust-sdk): format code

Signed-off-by: Xin Liu <[email protected]>

* chore(rust-sys): update `create_with_data` in ImportModule

Signed-off-by: Xin Liu <[email protected]>

* chore(rust-sdk): update `build_with_data` in ImportObjectBuilder

Signed-off-by: Xin Liu <[email protected]>

* feat(rust-types): implement Send and Sync for NeverType

Signed-off-by: Xin Liu <[email protected]>

* chore(rust-sys): update `host_data` in Instance

Signed-off-by: Xin Liu <[email protected]>

* chore(rust-sdk): update `host_data` in Instance

Signed-off-by: Xin Liu <[email protected]>

* chore(rust-sys): update `host_data` in Instance

Signed-off-by: Xin Liu <[email protected]>

* chore(rust-sdk): update `host_data` in Instance

Signed-off-by: Xin Liu <[email protected]>

* refactor(rust-sys): refactor `ImportModule`

Signed-off-by: Xin Liu <[email protected]>

* refactor(rust-sdk): refactor `ImportObjectBuilder` and `ImportObject`

Signed-off-by: Xin Liu <[email protected]>

* chore(rust-sdk): impl `Default` for `ImportObjectBuilder`

Signed-off-by: Xin Liu <[email protected]>

* chore(rust-sys): update example and test code

Signed-off-by: Xin Liu <[email protected]>

* chore(rust-sdk): update test code

Signed-off-by: Xin Liu <[email protected]>

---------

Signed-off-by: Xin Liu <[email protected]>
  • Loading branch information
apepkuss authored Jun 27, 2023
1 parent 1226136 commit bf2b840
Show file tree
Hide file tree
Showing 22 changed files with 317 additions and 167 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ fn interpreter_call_aot() -> Result<(), Box<dyn std::error::Error>> {
let mut store = Store::create()?;

// create an import module
let mut import = ImportModule::create("host")?;
let mut import = ImportModule::<NeverType>::create("host")?;

// import host_print_i32 as a host function
let func_ty = FuncType::create([ValType::I32], [])?;
Expand Down Expand Up @@ -132,7 +132,7 @@ fn aot_call_interpreter() -> Result<(), Box<dyn std::error::Error>> {
let mut store = Store::create()?;

// create an import module
let mut import = ImportModule::create("host")?;
let mut import = ImportModule::<NeverType>::create("host")?;

// import host_print_i32 as a host function
let func_ty = FuncType::create([ValType::I32], [])?;
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmedge-sys/examples/hostfunc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let host_func = Function::create::<NeverType>(&func_ty, real_add, None, 0)?;

// create an ImportObject module
let mut import = ImportModule::create("extern_module")?;
let mut import = ImportModule::<NeverType>::create("extern_module")?;
import.add_func("add", host_func);

// create a config
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmedge-sys/examples/hostfunc2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ fn real_add<T>(
#[cfg_attr(test, test)]
fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = Config::create()?;
let mut import = ImportModule::create("extern_module")?;
let mut import = ImportModule::<NeverType>::create("extern_module")?;

let result = FuncType::create(
vec![ValType::ExternRef, ValType::I32, ValType::I32],
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmedge-sys/examples/table_and_funcref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
table.set_data(WasmValue::from_func_ref(host_func.as_ref()), 3)?;

// add the table instance to the import object
let mut import = ImportModule::create("extern")?;
let mut import = ImportModule::<NeverType>::create("extern")?;
import.add_table("my-table", table);

// create a config
Expand Down
13 changes: 6 additions & 7 deletions crates/wasmedge-sys/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ impl Executor {
/// # Error
///
/// If fail to register the given [import object](crate::ImportObject), then an error is returned.
pub fn register_import_object(
pub fn register_import_object<T: Send + Sync + Clone>(
&mut self,
store: &mut Store,
import: &ImportObject,
import: &ImportObject<T>,
) -> WasmEdgeResult<()> {
match import {
ImportObject::Import(import) => unsafe {
Expand Down Expand Up @@ -446,7 +446,7 @@ mod tests {
let host_name = "extern";

// create an ImportObj module
let result = ImportModule::create(host_name);
let result = ImportModule::<NeverType>::create(host_name);
assert!(result.is_ok());
let mut import = result.unwrap();

Expand Down Expand Up @@ -597,7 +597,7 @@ mod tests {
let async_wasi_module = result.unwrap();

// register async_wasi module into the store
let wasi_import = ImportObject::AsyncWasi(async_wasi_module);
let wasi_import = ImportObject::<NeverType>::AsyncWasi(async_wasi_module);
let result = executor.register_import_object(&mut store, &wasi_import);
assert!(result.is_ok());

Expand Down Expand Up @@ -649,14 +649,13 @@ mod tests {
let async_wasi_module = result.unwrap();

// register async_wasi module into the store
let wasi_import = ImportObject::AsyncWasi(async_wasi_module);
let wasi_import = ImportObject::<NeverType>::AsyncWasi(async_wasi_module);
let result = executor.register_import_object(&mut store, &wasi_import);
assert!(result.is_ok());

// todo
let ty = FuncType::create([], [])?;
let async_hello_func = Function::create_async::<NeverType>(&ty, async_hello, None, 0)?;
let mut import = ImportModule::create("extern")?;
let mut import = ImportModule::<NeverType>::create("extern")?;
import.add_func("async_hello", async_hello_func);

let extern_import = ImportObject::Import(import);
Expand Down
135 changes: 119 additions & 16 deletions crates/wasmedge-sys/src/instance/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{
types::WasmEdgeString,
Function, Global, Memory, Table, WasmEdgeResult,
};
use std::sync::Arc;
use std::{os::raw::c_void, sync::Arc};
#[cfg(all(feature = "async", target_os = "linux"))]
use std::{path::PathBuf, sync::Mutex};

Expand Down Expand Up @@ -266,6 +266,19 @@ impl Instance {
}
}

/// Returns the host data held by the module instance.
pub fn host_data<T: Send + Sync + Clone>(&mut self) -> Option<&mut T> {
let ctx = unsafe { ffi::WasmEdge_ModuleInstanceGetHostData(self.inner.0) };

match ctx.is_null() {
true => None,
false => {
let ctx = unsafe { &mut *(ctx as *mut T) };
Some(ctx)
}
}
}

/// Provides a raw pointer to the inner module instance context.
#[cfg(feature = "ffi")]
pub fn as_ptr(&self) -> *const ffi::WasmEdge_ModuleInstanceContext {
Expand Down Expand Up @@ -357,14 +370,18 @@ pub trait AsInstance {
fn global_names(&self) -> Option<Vec<String>>;
}

/// The finalizer funtion used to free the host data.
pub type Finalizer = unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void);

/// An [ImportModule] represents a host module with a name. A host module consists of one or more host [function](crate::Function), [table](crate::Table), [memory](crate::Memory), and [global](crate::Global) instances, which are defined outside wasm modules and fed into wasm modules as imports.
#[derive(Debug, Clone)]
pub struct ImportModule {
pub struct ImportModule<T: Send + Sync + Clone> {
pub(crate) inner: Arc<InnerInstance>,
pub(crate) registered: bool,
name: String,
_host_data: Option<Box<T>>,
}
impl Drop for ImportModule {
impl<T: Send + Sync + Clone> Drop for ImportModule<T> {
fn drop(&mut self) {
if !self.registered && Arc::strong_count(&self.inner) == 1 && !self.inner.0.is_null() {
unsafe {
Expand All @@ -373,7 +390,7 @@ impl Drop for ImportModule {
}
}
}
impl ImportModule {
impl<T: Send + Sync + Clone> ImportModule<T> {
/// Creates a module instance which is used to import host functions, tables, memories, and globals into a wasm module.
///
/// # Argument
Expand All @@ -395,6 +412,47 @@ impl ImportModule {
inner: std::sync::Arc::new(InnerInstance(ctx)),
registered: false,
name: name.as_ref().to_string(),
_host_data: None,
}),
}
}

/// Creates a module instance with the given host data. The module instance is used to import host functions, tables, memories, and globals into a wasm module.
///
/// # Arguments
///
/// * `name` - The name of the import module instance.
///
/// * `host_data` - The host data to be stored in the module instance.
///
/// * `finalizer` - the function to drop the host data.
///
/// # Error
///
/// If fail to create the import module instance, then an error is returned.
pub fn create_with_data(
name: impl AsRef<str>,
mut host_data: Box<T>,
finalizer: Option<Finalizer>,
) -> WasmEdgeResult<Self> {
let raw_name = WasmEdgeString::from(name.as_ref());
let ctx = unsafe {
ffi::WasmEdge_ModuleInstanceCreateWithData(
raw_name.as_raw(),
host_data.as_mut() as *mut T as *mut c_void,
finalizer,
)
};

match ctx.is_null() {
true => Err(Box::new(WasmEdgeError::Instance(
InstanceError::CreateImportModule,
))),
false => Ok(Self {
inner: std::sync::Arc::new(InnerInstance(ctx)),
registered: false,
name: name.as_ref().to_string(),
_host_data: Some(host_data),
}),
}
}
Expand All @@ -405,7 +463,7 @@ impl ImportModule {
self.inner.0 as *const _
}
}
impl AsImport for ImportModule {
impl<T: Send + Sync + Clone> AsImport for ImportModule<T> {
fn name(&self) -> &str {
self.name.as_str()
}
Expand Down Expand Up @@ -1310,17 +1368,17 @@ pub trait AsImport {

/// Defines three types of module instances that can be imported into a WasmEdge [Store](crate::Store) instance.
#[derive(Debug, Clone)]
pub enum ImportObject {
pub enum ImportObject<T: Send + Sync + Clone> {
/// Defines the import module instance of ImportModule type.
Import(ImportModule),
Import(ImportModule<T>),
/// Defines the import module instance of WasiModule type.
#[cfg(not(feature = "async"))]
Wasi(WasiModule),
/// Defines the import module instance of AsyncWasiModule type.
#[cfg(all(feature = "async", target_os = "linux"))]
AsyncWasi(AsyncWasiModule),
}
impl ImportObject {
impl<T: Send + Sync + Clone> ImportObject<T> {
/// Returns the name of the import object.
pub fn name(&self) -> &str {
match self {
Expand Down Expand Up @@ -1365,7 +1423,7 @@ mod tests {
let host_name = "extern";

// create an import module
let result = ImportModule::create(host_name);
let result = ImportModule::<NeverType>::create(host_name);
assert!(result.is_ok());
let mut import = result.unwrap();

Expand Down Expand Up @@ -1416,7 +1474,7 @@ mod tests {
let host_name = "extern";

// create an ImportModule instance
let result = ImportModule::create(host_name);
let result = ImportModule::<NeverType>::create(host_name);
assert!(result.is_ok());
let import = result.unwrap();

Expand All @@ -1434,7 +1492,7 @@ mod tests {
let host_name = "extern";

// create an ImportModule instance
let result = ImportModule::create(host_name);
let result = ImportModule::<NeverType>::create(host_name);
assert!(result.is_ok());
let mut import = result.unwrap();

Expand Down Expand Up @@ -1583,7 +1641,7 @@ mod tests {
let module_name = "extern_module";

// create ImportModule instance
let result = ImportModule::create(module_name);
let result = ImportModule::<NeverType>::create(module_name);
assert!(result.is_ok());
let mut import = result.unwrap();

Expand Down Expand Up @@ -1705,7 +1763,7 @@ mod tests {
let module_name = "extern_module";

// create ImportModule instance
let result = ImportModule::create(module_name);
let result = ImportModule::<NeverType>::create(module_name);
assert!(result.is_ok());
let mut import = result.unwrap();

Expand Down Expand Up @@ -1802,7 +1860,7 @@ mod tests {
assert!(store.module_names().is_none());

// create ImportObject instance
let result = ImportModule::create(module_name);
let result = ImportModule::<NeverType>::create(module_name);
assert!(result.is_ok());
let mut import = result.unwrap();

Expand Down Expand Up @@ -1857,7 +1915,7 @@ mod tests {

let result = store.module(module_name);
assert!(result.is_ok());
let instance = result.unwrap();
let mut instance = result.unwrap();

// get the exported memory
let result = instance.get_memory("mem");
Expand All @@ -1868,6 +1926,9 @@ mod tests {
let ty = result.unwrap();
assert_eq!(ty.min(), 10);
assert_eq!(ty.max(), Some(20));

// get host data
assert!(instance.host_data::<NeverType>().is_none());
}

#[sys_host_function]
Expand Down Expand Up @@ -1906,7 +1967,7 @@ mod tests {
let host_name = "extern";

// create an import module
let result = ImportModule::create(host_name);
let result = ImportModule::<NeverType>::create(host_name);
assert!(result.is_ok());
let mut import = result.unwrap();

Expand Down Expand Up @@ -2003,4 +2064,46 @@ mod tests {
drop(wasi_import_clone);
}
}

#[test]
fn test_instance_create_import_with_data() {
let module_name = "extern_module";

// define host data
#[derive(Clone, Debug)]
struct Circle {
radius: i32,
}

let circle = Box::new(Circle { radius: 10 });
// create an import module
let result = ImportModule::create_with_data(module_name, circle, None);

assert!(result.is_ok());
let import = result.unwrap();

let result = Config::create();
assert!(result.is_ok());
let config = result.unwrap();
let result = Executor::create(Some(&config), None);
assert!(result.is_ok());
let mut executor = result.unwrap();

let result = Store::create();
assert!(result.is_ok());
let mut store = result.unwrap();

let import = ImportObject::Import(import);
let result = executor.register_import_object(&mut store, &import);
assert!(result.is_ok());

let result = store.module(module_name);
assert!(result.is_ok());
let mut instance = result.unwrap();

let result = instance.host_data::<Circle>();
assert!(result.is_some());
let host_data = result.unwrap();
assert_eq!(host_data.radius, 10);
}
}
2 changes: 1 addition & 1 deletion crates/wasmedge-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ pub use instance::{
function::{FuncRef, FuncType, Function, HostFn},
global::{Global, GlobalType},
memory::{MemType, Memory},
module::{AsImport, AsInstance, ImportModule, ImportObject, Instance},
module::{AsImport, AsInstance, Finalizer, ImportModule, ImportObject, Instance},
table::{Table, TableType},
};
#[doc(inline)]
Expand Down
4 changes: 2 additions & 2 deletions crates/wasmedge-sys/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ mod tests {
assert!(store.module_names().is_none());

// create ImportObject instance
let result = ImportModule::create(module_name);
let result = ImportModule::<NeverType>::create(module_name);
assert!(result.is_ok());
let mut import = result.unwrap();

Expand Down Expand Up @@ -239,7 +239,7 @@ mod tests {
let store_cloned = Arc::clone(&store);
let handle = thread::spawn(move || {
// create ImportObject instance
let result = ImportModule::create("extern_module");
let result = ImportModule::<NeverType>::create("extern_module");
assert!(result.is_ok());
let mut import = result.unwrap();

Expand Down
2 changes: 1 addition & 1 deletion crates/wasmedge-sys/tests/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use wasmedge_macro::sys_host_function;
use wasmedge_sys::{AsImport, CallingFrame, FuncType, Function, ImportModule, WasmValue};
use wasmedge_types::{error::HostFuncError, NeverType, ValType};

pub fn create_extern_module(name: impl AsRef<str>) -> ImportModule {
pub fn create_extern_module(name: impl AsRef<str>) -> ImportModule<NeverType> {
// create an import module
let result = ImportModule::create(name);
assert!(result.is_ok());
Expand Down
Loading

0 comments on commit bf2b840

Please sign in to comment.