Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] Support new c-apis #13

Merged
merged 18 commits into from
Jun 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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