mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-13 13:58:38 +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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
1
lib/c-api/src/wasm_c_api/externals/mod.rs
vendored
1
lib/c-api/src/wasm_c_api/externals/mod.rs
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
pub mod function;
|
||||||
pub mod global;
|
pub mod global;
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
pub mod table;
|
pub mod table;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ pub mod wasi;
|
|||||||
// https://github.com/rust-lang/rust/issues/57966
|
// https://github.com/rust-lang/rust/issues/57966
|
||||||
use crate::c_try;
|
use crate::c_try;
|
||||||
use crate::ordered_resolver::OrderedResolver;
|
use crate::ordered_resolver::OrderedResolver;
|
||||||
|
use externals::function::wasm_func_t;
|
||||||
use externals::global::wasm_global_t;
|
use externals::global::wasm_global_t;
|
||||||
use externals::memory::wasm_memory_t;
|
use externals::memory::wasm_memory_t;
|
||||||
use externals::table::wasm_table_t;
|
use externals::table::wasm_table_t;
|
||||||
@@ -23,8 +24,8 @@ use std::sync::Arc;
|
|||||||
use store::wasm_store_t;
|
use store::wasm_store_t;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use wasmer::{
|
use wasmer::{
|
||||||
ExportType, Extern, ExternType, Function, FunctionType, GlobalType, ImportType, Instance,
|
ExportType, Extern, ExternType, FunctionType, GlobalType, ImportType, Instance, MemoryType,
|
||||||
MemoryType, Module, Mutability, Pages, RuntimeError, Store, TableType, Val, ValType,
|
Module, Mutability, Pages, RuntimeError, Store, TableType, Val, ValType,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "jit")]
|
#[cfg(feature = "jit")]
|
||||||
use wasmer_engine_jit::JIT;
|
use wasmer_engine_jit::JIT;
|
||||||
@@ -579,167 +580,9 @@ impl TryFrom<&Val> for wasm_val_t {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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)]
|
#[allow(non_camel_case_types)]
|
||||||
pub type wasm_env_finalizer_t = unsafe extern "C" fn(c_void);
|
pub type wasm_env_finalizer_t = unsafe extern "C" fn(c_void);
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct wasm_func_t {
|
|
||||||
inner: Function,
|
|
||||||
// this is how we ensure the instance stays alive
|
|
||||||
instance: Option<Arc<Instance>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! wasm_declare_vec_inner {
|
macro_rules! wasm_declare_vec_inner {
|
||||||
($name:ident) => {
|
($name:ident) => {
|
||||||
paste::item! {
|
paste::item! {
|
||||||
|
|||||||
Reference in New Issue
Block a user