Add a wasmtime_linker_define_func C API function (#3122)
This exposes the functionality of the `Linker` type where a store-independent function can be created and inserted, allowing a linker's functions to be used across many stores (instead of requiring one linker-per-store). Closes #3110
This commit is contained in:
@@ -80,6 +80,41 @@ WASM_API_EXTERN wasmtime_error_t* wasmtime_linker_define(
|
|||||||
const wasmtime_extern_t *item
|
const wasmtime_extern_t *item
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Defines a new function in this linker.
|
||||||
|
*
|
||||||
|
* \param linker the linker the name is being defined in.
|
||||||
|
* \param module the module name the item is defined under.
|
||||||
|
* \param module_len the byte length of `module`
|
||||||
|
* \param name the field name the item is defined under
|
||||||
|
* \param name_len the byte length of `name`
|
||||||
|
* \param ty the type of the function that's being defined
|
||||||
|
* \param cb the host callback to invoke when the function is called
|
||||||
|
* \param data the host-provided data to provide as the first argument to the callback
|
||||||
|
* \param finalizer an optional finalizer for the `data` argument.
|
||||||
|
*
|
||||||
|
* \return On success `NULL` is returned, otherwise an error is returned which
|
||||||
|
* describes why the definition failed.
|
||||||
|
*
|
||||||
|
* For more information about name resolution consult the [Rust
|
||||||
|
* documentation](https://bytecodealliance.github.io/wasmtime/api/wasmtime/struct.Linker.html#name-resolution).
|
||||||
|
*
|
||||||
|
* Note that this function does not create a #wasmtime_func_t. This creates a
|
||||||
|
* store-independent function within the linker, allowing this function
|
||||||
|
* definition to be used with multiple stores.
|
||||||
|
*/
|
||||||
|
WASM_API_EXTERN wasmtime_error_t* wasmtime_linker_define_func(
|
||||||
|
wasmtime_linker_t *linker,
|
||||||
|
const char *module,
|
||||||
|
size_t module_len,
|
||||||
|
const char *name,
|
||||||
|
size_t name_len,
|
||||||
|
const wasm_functype_t *ty,
|
||||||
|
wasmtime_func_callback_t cb,
|
||||||
|
void *data,
|
||||||
|
void (*finalizer)(void*)
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Defines WASI functions in this linker.
|
* \brief Defines WASI functions in this linker.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use std::mem::MaybeUninit;
|
|||||||
use std::panic::{self, AssertUnwindSafe};
|
use std::panic::{self, AssertUnwindSafe};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::str;
|
use std::str;
|
||||||
use wasmtime::{AsContextMut, Caller, Extern, Func, Trap};
|
use wasmtime::{AsContextMut, Caller, Extern, Func, Trap, Val};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
@@ -187,25 +187,37 @@ pub struct wasmtime_caller_t<'a> {
|
|||||||
caller: Caller<'a, crate::StoreData>,
|
caller: Caller<'a, crate::StoreData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
pub type wasmtime_func_callback_t = extern "C" fn(
|
||||||
pub unsafe extern "C" fn wasmtime_func_new(
|
|
||||||
store: CStoreContextMut<'_>,
|
|
||||||
ty: &wasm_functype_t,
|
|
||||||
callback: extern "C" fn(
|
|
||||||
*mut c_void,
|
*mut c_void,
|
||||||
*mut wasmtime_caller_t,
|
*mut wasmtime_caller_t,
|
||||||
*const wasmtime_val_t,
|
*const wasmtime_val_t,
|
||||||
usize,
|
usize,
|
||||||
*mut wasmtime_val_t,
|
*mut wasmtime_val_t,
|
||||||
usize,
|
usize,
|
||||||
) -> Option<Box<wasm_trap_t>>,
|
) -> Option<Box<wasm_trap_t>>;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasmtime_func_new(
|
||||||
|
store: CStoreContextMut<'_>,
|
||||||
|
ty: &wasm_functype_t,
|
||||||
|
callback: wasmtime_func_callback_t,
|
||||||
data: *mut c_void,
|
data: *mut c_void,
|
||||||
finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>,
|
finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>,
|
||||||
func: &mut Func,
|
func: &mut Func,
|
||||||
) {
|
) {
|
||||||
let foreign = crate::ForeignData { data, finalizer };
|
|
||||||
let ty = ty.ty().ty.clone();
|
let ty = ty.ty().ty.clone();
|
||||||
let f = Func::new(store, ty, move |caller, params, results| {
|
let cb = c_callback_to_rust_fn(callback, data, finalizer);
|
||||||
|
let f = Func::new(store, ty, cb);
|
||||||
|
*func = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) unsafe fn c_callback_to_rust_fn(
|
||||||
|
callback: wasmtime_func_callback_t,
|
||||||
|
data: *mut c_void,
|
||||||
|
finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>,
|
||||||
|
) -> impl Fn(Caller<'_, crate::StoreData>, &[Val], &mut [Val]) -> Result<(), Trap> {
|
||||||
|
let foreign = crate::ForeignData { data, finalizer };
|
||||||
|
move |caller, params, results| {
|
||||||
let params = params
|
let params = params
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
@@ -234,8 +246,7 @@ pub unsafe extern "C" fn wasmtime_func_new(
|
|||||||
results[i] = unsafe { result.to_val() };
|
results[i] = unsafe { result.to_val() };
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
}
|
||||||
*func = f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
use crate::func::c_callback_to_rust_fn;
|
||||||
use crate::{
|
use crate::{
|
||||||
bad_utf8, handle_result, wasm_engine_t, wasm_trap_t, wasmtime_error_t, wasmtime_extern_t,
|
bad_utf8, handle_result, wasm_engine_t, wasm_functype_t, wasm_trap_t, wasmtime_error_t,
|
||||||
wasmtime_module_t, CStoreContextMut,
|
wasmtime_extern_t, wasmtime_func_callback_t, wasmtime_module_t, CStoreContextMut,
|
||||||
};
|
};
|
||||||
|
use std::ffi::c_void;
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
use std::str;
|
use std::str;
|
||||||
use wasmtime::{Func, Instance, Linker};
|
use wasmtime::{Func, Instance, Linker};
|
||||||
@@ -54,6 +56,25 @@ pub unsafe extern "C" fn wasmtime_linker_define(
|
|||||||
handle_result(linker.define(module, name, item), |_linker| ())
|
handle_result(linker.define(module, name, item), |_linker| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasmtime_linker_define_func(
|
||||||
|
linker: &mut wasmtime_linker_t,
|
||||||
|
module: *const u8,
|
||||||
|
module_len: usize,
|
||||||
|
name: *const u8,
|
||||||
|
name_len: usize,
|
||||||
|
ty: &wasm_functype_t,
|
||||||
|
callback: wasmtime_func_callback_t,
|
||||||
|
data: *mut c_void,
|
||||||
|
finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>,
|
||||||
|
) -> Option<Box<wasmtime_error_t>> {
|
||||||
|
let ty = ty.ty().ty.clone();
|
||||||
|
let module = to_str!(module, module_len);
|
||||||
|
let name = to_str!(name, name_len);
|
||||||
|
let cb = c_callback_to_rust_fn(callback, data, finalizer);
|
||||||
|
handle_result(linker.linker.func_new(module, name, ty, cb), |_linker| ())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "wasi")]
|
#[cfg(feature = "wasi")]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wasmtime_linker_define_wasi(
|
pub extern "C" fn wasmtime_linker_define_wasi(
|
||||||
|
|||||||
Reference in New Issue
Block a user