mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-08 21:58:20 +00:00
feat(c-api) Move function into its own module.
This commit is contained in:
169
lib/c-api/src/wasm_c_api/externals/function.rs
vendored
Normal file
169
lib/c-api/src/wasm_c_api/externals/function.rs
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
use super::super::{
|
||||
wasm_functype_t, wasm_store_t, wasm_trap_t, wasm_val_inner, wasm_val_t, wasm_valkind_enum,
|
||||
};
|
||||
use std::convert::TryInto;
|
||||
use std::ffi::c_void;
|
||||
use std::ptr::NonNull;
|
||||
use std::sync::Arc;
|
||||
use wasmer::{Function, Instance, RuntimeError, Store, Val};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct wasm_func_t {
|
||||
pub(crate) inner: Function,
|
||||
// this is how we ensure the instance stays alive
|
||||
pub(crate) instance: Option<Arc<Instance>>,
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type wasm_func_callback_t =
|
||||
unsafe extern "C" fn(args: *const wasm_val_t, results: *mut wasm_val_t) -> *mut wasm_trap_t;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type wasm_func_callback_with_env_t = unsafe extern "C" fn(
|
||||
*mut c_void,
|
||||
args: *const wasm_val_t,
|
||||
results: *mut wasm_val_t,
|
||||
) -> *mut wasm_trap_t;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type wasm_env_finalizer_t = unsafe extern "C" fn(c_void);
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_func_new(
|
||||
store: Option<NonNull<wasm_store_t>>,
|
||||
ft: &wasm_functype_t,
|
||||
callback: wasm_func_callback_t,
|
||||
) -> Option<Box<wasm_func_t>> {
|
||||
// TODO: handle null pointers?
|
||||
let store_ptr = store?.cast::<Store>();
|
||||
let store = store_ptr.as_ref();
|
||||
let func_sig = ft.sig();
|
||||
let num_rets = func_sig.results().len();
|
||||
let inner_callback = move |args: &[Val]| -> Result<Vec<Val>, RuntimeError> {
|
||||
let processed_args = args
|
||||
.into_iter()
|
||||
.map(TryInto::try_into)
|
||||
.collect::<Result<Vec<wasm_val_t>, _>>()
|
||||
.expect("Argument conversion failed");
|
||||
|
||||
let mut results = vec![
|
||||
wasm_val_t {
|
||||
kind: wasm_valkind_enum::WASM_I64 as _,
|
||||
of: wasm_val_inner { int64_t: 0 },
|
||||
};
|
||||
num_rets
|
||||
];
|
||||
|
||||
let _traps = callback(processed_args.as_ptr(), results.as_mut_ptr());
|
||||
// TODO: do something with `traps`
|
||||
|
||||
let processed_results = results
|
||||
.into_iter()
|
||||
.map(TryInto::try_into)
|
||||
.collect::<Result<Vec<Val>, _>>()
|
||||
.expect("Result conversion failed");
|
||||
Ok(processed_results)
|
||||
};
|
||||
let f = Function::new(store, &func_sig, inner_callback);
|
||||
Some(Box::new(wasm_func_t {
|
||||
instance: None,
|
||||
inner: f,
|
||||
}))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_func_new_with_env(
|
||||
store: Option<NonNull<wasm_store_t>>,
|
||||
ft: &wasm_functype_t,
|
||||
callback: wasm_func_callback_with_env_t,
|
||||
env: *mut c_void,
|
||||
finalizer: wasm_env_finalizer_t,
|
||||
) -> Option<Box<wasm_func_t>> {
|
||||
// TODO: handle null pointers?
|
||||
let store_ptr = store?.cast::<Store>();
|
||||
let store = store_ptr.as_ref();
|
||||
let func_sig = ft.sig();
|
||||
let num_rets = func_sig.results().len();
|
||||
let inner_callback =
|
||||
move |env: &mut *mut c_void, args: &[Val]| -> Result<Vec<Val>, RuntimeError> {
|
||||
let processed_args = args
|
||||
.into_iter()
|
||||
.map(TryInto::try_into)
|
||||
.collect::<Result<Vec<wasm_val_t>, _>>()
|
||||
.expect("Argument conversion failed");
|
||||
|
||||
let mut results = vec![
|
||||
wasm_val_t {
|
||||
kind: wasm_valkind_enum::WASM_I64 as _,
|
||||
of: wasm_val_inner { int64_t: 0 },
|
||||
};
|
||||
num_rets
|
||||
];
|
||||
|
||||
let _traps = callback(*env, processed_args.as_ptr(), results.as_mut_ptr());
|
||||
// TODO: do something with `traps`
|
||||
|
||||
let processed_results = results
|
||||
.into_iter()
|
||||
.map(TryInto::try_into)
|
||||
.collect::<Result<Vec<Val>, _>>()
|
||||
.expect("Result conversion failed");
|
||||
Ok(processed_results)
|
||||
};
|
||||
let f = Function::new_with_env(store, &func_sig, env, inner_callback);
|
||||
Some(Box::new(wasm_func_t {
|
||||
instance: None,
|
||||
inner: f,
|
||||
}))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_func_delete(_func: Option<Box<wasm_func_t>>) {}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_func_call(
|
||||
func: &wasm_func_t,
|
||||
args: *const wasm_val_t,
|
||||
results: *mut wasm_val_t,
|
||||
) -> Option<NonNull<wasm_trap_t>> {
|
||||
let num_params = func.inner.ty().params().len();
|
||||
let params: Vec<Val> = (0..num_params)
|
||||
.map(|i| (&(*args.add(i))).try_into())
|
||||
.collect::<Result<_, _>>()
|
||||
.ok()?;
|
||||
|
||||
match func.inner.call(¶ms) {
|
||||
Ok(wasm_results) => {
|
||||
for (i, actual_result) in wasm_results.iter().enumerate() {
|
||||
let result_loc = &mut (*results.add(i));
|
||||
*result_loc = (&*actual_result).try_into().ok()?;
|
||||
}
|
||||
None
|
||||
}
|
||||
Err(e) => Some(NonNull::new_unchecked(Box::into_raw(Box::new(e)) as _)),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_func_param_arity(func: &wasm_func_t) -> usize {
|
||||
func.inner.ty().params().len()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_func_result_arity(func: &wasm_func_t) -> usize {
|
||||
func.inner.ty().results().len()
|
||||
}
|
||||
|
||||
macro_rules! wasm_declare_own {
|
||||
($name:ident) => {
|
||||
paste::item! {
|
||||
#[repr(C)]
|
||||
pub struct [<wasm_ $name _t>] {}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn [<wasm_ $name _delete>](_arg: *mut [<wasm_ $name _t>]) {
|
||||
todo!("in generated delete")
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user