Skip to content

Commit

Permalink
[feat] Introduce PluginModule and PluginModuleBuilder (#14)
Browse files Browse the repository at this point in the history
* feat(rust-sys): implement `PluginModule`

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

* feat(rust-sdk): implement `PluginModuleBuilder` and `PluginModule`

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

* chore(rust-sys): format code

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

* chore(rust-sdk): format code

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

* chore(rust-sys): update code in `plugin`

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

---------

Signed-off-by: Xin Liu <[email protected]>
  • Loading branch information
apepkuss authored Jun 28, 2023
1 parent bf2b840 commit 1bd90ea
Show file tree
Hide file tree
Showing 19 changed files with 387 additions and 112 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::<NeverType>::create("host")?;
let mut import = ImportModule::<NeverType>::create("host", None)?;

// 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::<NeverType>::create("host")?;
let mut import = ImportModule::<NeverType>::create("host", None)?;

// 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::<NeverType>::create("extern_module")?;
let mut import = ImportModule::<NeverType>::create("extern_module", None)?;
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::<NeverType>::create("extern_module")?;
let mut import = ImportModule::<NeverType>::create("extern_module", None)?;

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::<NeverType>::create("extern")?;
let mut import = ImportModule::<NeverType>::create("extern", None)?;
import.add_table("my-table", table);

// create a config
Expand Down
4 changes: 2 additions & 2 deletions crates/wasmedge-sys/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ mod tests {
let host_name = "extern";

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

Expand Down Expand Up @@ -655,7 +655,7 @@ mod tests {

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

let extern_import = ImportObject::Import(import);
Expand Down
89 changes: 33 additions & 56 deletions crates/wasmedge-sys/src/instance/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,9 +370,6 @@ 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<T: Send + Sync + Clone> {
Expand All @@ -397,63 +394,43 @@ impl<T: Send + Sync + Clone> ImportModule<T> {
///
/// * `name` - The name of the import module instance.
///
/// # Error
///
/// If fail to create the import module instance, then an error is returned.
pub fn create(name: impl AsRef<str>) -> WasmEdgeResult<Self> {
let raw_name = WasmEdgeString::from(name.as_ref());
let ctx = unsafe { ffi::WasmEdge_ModuleInstanceCreate(raw_name.as_raw()) };

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: 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> {
pub fn create(name: impl AsRef<str>, mut host_data: Option<Box<T>>) -> 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,
)

let ctx = match host_data.as_mut() {
Some(data) => unsafe {
ffi::WasmEdge_ModuleInstanceCreateWithData(
raw_name.as_raw(),
data.as_mut() as *mut T as *mut c_void,
None,
)
},
None => unsafe { ffi::WasmEdge_ModuleInstanceCreate(raw_name.as_raw()) },
};

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),
}),
false => match host_data.is_some() {
true => Ok(Self {
inner: std::sync::Arc::new(InnerInstance(ctx)),
registered: false,
name: name.as_ref().to_string(),
_host_data: host_data,
}),
false => Ok(Self {
inner: std::sync::Arc::new(InnerInstance(ctx)),
registered: false,
name: name.as_ref().to_string(),
_host_data: None,
}),
},
}
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Expand Down Expand Up @@ -2077,7 +2054,7 @@ mod tests {

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

assert!(result.is_ok());
let import = result.unwrap();
Expand Down
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, Finalizer, ImportModule, ImportObject, Instance},
module::{AsImport, AsInstance, ImportModule, ImportObject, Instance},
table::{Table, TableType},
};
#[doc(inline)]
Expand Down
121 changes: 118 additions & 3 deletions crates/wasmedge-sys/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
use super::ffi;
use crate::{
error::WasmEdgeError, instance::module::InnerInstance, types::WasmEdgeString, utils, Instance,
WasmEdgeResult,
error::{InstanceError, WasmEdgeError},
instance::{module::InnerInstance, Function, Global, Memory, Table},
types::WasmEdgeString,
utils, AsImport, Instance, WasmEdgeResult,
};
use std::ffi::CString;
use std::{ffi::CString, os::raw::c_void, sync::Arc};

/// Defines the APIs for loading plugins and check the basic information of the loaded plugins.
#[derive(Debug)]
Expand Down Expand Up @@ -456,6 +458,119 @@ impl PluginDescriptor {
}
}

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

/// Represents a Plugin module instance.
#[derive(Debug, Clone)]
pub struct PluginModule<T: Send + Sync + Clone> {
pub(crate) inner: Arc<InnerInstance>,
pub(crate) registered: bool,
name: String,
_host_data: Option<Box<T>>,
}
impl<T: Send + Sync + Clone> Drop for PluginModule<T> {
fn drop(&mut self) {
if !self.registered && Arc::strong_count(&self.inner) == 1 && !self.inner.0.is_null() {
unsafe {
ffi::WasmEdge_ModuleInstanceDelete(self.inner.0);
}
}
}
}
impl<T: Send + Sync + Clone> PluginModule<T> {
/// Creates a module instance which is used to import host functions, tables, memories, and globals into a wasm module.
///
/// # Argument
///
/// * `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. This argument is only available when `host_data` is set.
///
/// # Error
///
/// If fail to create the import module instance, then an error is returned.
pub fn create(
name: impl AsRef<str>,
mut host_data: Option<Box<T>>,
finalizer: Option<Finalizer>,
) -> WasmEdgeResult<Self> {
let raw_name = WasmEdgeString::from(name.as_ref());

let ctx = match host_data.as_mut() {
Some(data) => unsafe {
ffi::WasmEdge_ModuleInstanceCreateWithData(
raw_name.as_raw(),
data.as_mut() as *mut T as *mut c_void,
finalizer,
)
},
None => unsafe { ffi::WasmEdge_ModuleInstanceCreate(raw_name.as_raw()) },
};

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: host_data,
}),
}
}

/// Provides a raw pointer to the inner module instance context.
#[cfg(feature = "ffi")]
pub fn as_raw_ptr(&self) -> *const ffi::WasmEdge_ModuleInstanceContext {
self.inner.0 as *const _
}
}
impl<T: Send + Sync + Clone> AsImport for PluginModule<T> {
fn name(&self) -> &str {
self.name.as_str()
}

fn add_func(&mut self, name: impl AsRef<str>, mut func: Function) {
let func_name: WasmEdgeString = name.into();
unsafe {
ffi::WasmEdge_ModuleInstanceAddFunction(self.inner.0, func_name.as_raw(), func.inner.0);
}
func.registered = true;
}

fn add_table(&mut self, name: impl AsRef<str>, mut table: Table) {
let table_name: WasmEdgeString = name.as_ref().into();
unsafe {
ffi::WasmEdge_ModuleInstanceAddTable(self.inner.0, table_name.as_raw(), table.inner.0);
}
table.registered = true;
}

fn add_memory(&mut self, name: impl AsRef<str>, mut memory: Memory) {
let mem_name: WasmEdgeString = name.as_ref().into();
unsafe {
ffi::WasmEdge_ModuleInstanceAddMemory(self.inner.0, mem_name.as_raw(), memory.inner.0);
}
memory.registered = true;
}

fn add_global(&mut self, name: impl AsRef<str>, mut global: Global) {
let global_name: WasmEdgeString = name.as_ref().into();
unsafe {
ffi::WasmEdge_ModuleInstanceAddGlobal(
self.inner.0,
global_name.as_raw(),
global.inner.0,
);
}
global.registered = true;
}
}

#[cfg(test)]
mod tests {

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::<NeverType>::create(module_name);
let result = ImportModule::<NeverType>::create(module_name, None);
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::<NeverType>::create("extern_module");
let result = ImportModule::<NeverType>::create("extern_module", None);
assert!(result.is_ok());
let mut import = result.unwrap();

Expand Down
Loading

0 comments on commit 1bd90ea

Please sign in to comment.