Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
36 changes: 31 additions & 5 deletions crates/c-api/include/wasmtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -515,8 +515,7 @@ typedef own wasm_trap_t* (*wasmtime_func_callback_t)(const wasmtime_caller_t* ca
*
* This function is the same as #wasm_func_callback_with_env_t except that its
* first argument is a #wasmtime_caller_t which allows learning information
* about the
* caller.
* about the caller.
*/
typedef own wasm_trap_t* (*wasmtime_func_callback_with_env_t)(const wasmtime_caller_t* caller, void* env, const wasm_val_t args[], wasm_val_t results[]);

Expand Down Expand Up @@ -544,6 +543,28 @@ WASM_API_EXTERN own wasm_func_t* wasmtime_func_new_with_env(
void (*finalizer)(void*)
);

/**
* \brief Creates a new `funcref` value referencing `func`.
*
* Create a `funcref` value that references `func` and writes it to `funcrefp`.
*
* Gives ownership fo the `funcref` value written to `funcrefp`.
*
* Both `func` and `funcrefp` must not be NULL.
*/
WASM_API_EXTERN void wasmtime_func_as_funcref(const wasm_func_t* func, wasm_val_t* funcrefp);

/**
* \brief Get the `wasm_func_t*` referenced by the given `funcref` value.
*
* Gets an owning handle to the `wasm_func_t*` that the given `funcref` value is
* referencing. Returns NULL if the value is not a `funcref`, or if the value is
* a null function reference.
*
* The `val` pointer must not be NULL.
*/
WASM_API_EXTERN own wasm_func_t* wasmtime_funcref_as_func(const wasm_val_t* val);

/**
* \brief Loads a #wasm_extern_t from the caller's context
*
Expand Down Expand Up @@ -845,8 +866,10 @@ WASM_API_EXTERN wasmtime_error_t *wasmtime_funcref_table_grow(
* This function does not take an associated finalizer to clean up the data when
* the reference is reclaimed. If you need a finalizer to clean up the data,
* then use #wasmtime_externref_new_with_finalizer.
*
* Gives ownership of the newly created `externref` value.
*/
WASM_API_EXTERN void wasmtime_externref_new(void *data, wasm_val_t *valp);
WASM_API_EXTERN void wasmtime_externref_new(own void *data, wasm_val_t *valp);

/**
* \brief A finalizer for an `externref`'s wrapped data.
Expand All @@ -866,9 +889,11 @@ typedef void (*wasmtime_externref_finalizer_t)(void*);
* When the reference is reclaimed, the wrapped data is cleaned up with the
* provided finalizer. If you do not need to clean up the wrapped data, then use
* #wasmtime_externref_new.
*
* Gives ownership of the newly created `externref` value.
*/
WASM_API_EXTERN void wasmtime_externref_new_with_finalizer(
void *data,
own void *data,
wasmtime_externref_finalizer_t finalizer,
wasm_val_t *valp
);
Expand All @@ -887,7 +912,8 @@ WASM_API_EXTERN void wasmtime_externref_new_with_finalizer(
* If the given value is not an `externref`, returns `false` and leaves `datap`
* unmodified.
*
* Does not take ownership of `val`.
* Does not take ownership of `val`. Does not give up ownership of the `void*`
* data written to `datap`.
*
* Both `val` and `datap` must not be `NULL`.
*/
Expand Down
20 changes: 19 additions & 1 deletion crates/c-api/src/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::mem::MaybeUninit;
use std::panic::{self, AssertUnwindSafe};
use std::ptr;
use std::str;
use wasmtime::{Caller, Extern, Func, Trap};
use wasmtime::{Caller, Extern, Func, Trap, Val};

#[derive(Clone)]
#[repr(transparent)]
Expand Down Expand Up @@ -275,3 +275,21 @@ pub extern "C" fn wasmtime_caller_export_get(
let which = caller.caller.get_export(name)?;
Some(Box::new(wasm_extern_t { which }))
}

#[no_mangle]
pub extern "C" fn wasmtime_func_as_funcref(
func: &wasm_func_t,
funcrefp: &mut MaybeUninit<wasm_val_t>,
) {
let funcref = wasm_val_t::from_val(Val::FuncRef(Some(func.func().clone())));
crate::initialize(funcrefp, funcref);
}

#[no_mangle]
pub extern "C" fn wasmtime_funcref_as_func(val: &wasm_val_t) -> Option<Box<wasm_func_t>> {
if let Val::FuncRef(Some(f)) = val.val() {
Some(Box::new(f.into()))
} else {
None
}
}
2 changes: 1 addition & 1 deletion crates/c-api/src/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ pub extern "C" fn wasm_table_get(
index: wasm_table_size_t,
) -> Option<Box<wasm_ref_t>> {
let val = t.table().get(index)?;
Some(val_into_ref(val).unwrap())
val_into_ref(val)
}

#[no_mangle]
Expand Down
19 changes: 17 additions & 2 deletions crates/c-api/src/val.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ impl Drop for wasm_val_t {
fn drop(&mut self) {
match into_valtype(self.kind) {
ValType::ExternRef => unsafe {
drop(Box::from_raw(self.of.ref_));
if !self.of.ref_.is_null() {
drop(Box::from_raw(self.of.ref_));
}
},
_ => {}
}
Expand Down Expand Up @@ -116,7 +118,20 @@ impl wasm_val_t {
ValType::I64 => Val::from(unsafe { self.of.i64 }),
ValType::F32 => Val::from(unsafe { self.of.f32 }),
ValType::F64 => Val::from(unsafe { self.of.f64 }),
ValType::ExternRef | ValType::FuncRef => ref_to_val(unsafe { &*self.of.ref_ }),
ValType::ExternRef => unsafe {
if self.of.ref_.is_null() {
Val::ExternRef(None)
} else {
ref_to_val(&*self.of.ref_)
}
},
ValType::FuncRef => unsafe {
if self.of.ref_.is_null() {
Val::FuncRef(None)
} else {
ref_to_val(&*self.of.ref_)
}
},
_ => unimplemented!("wasm_val_t::val {:?}", self.kind),
}
}
Expand Down