Skip to content

Commit a9455a8

Browse files
authored
C API tweaks for wasmtime-py (#2029)
* wasmtime-c-api: Only drop non-null `*mut wasm_ref_t`s * wasmtime-c-api: Handle null refs in `wasm_val_t` to `Val` conversion * wasmtime-c-api: Don't unwrap and rewrap `Option`s The `unwrap` can panic, and there isn't any point to this unwrap+rewrap. * wasmtime-c-api: Add conversions between `funcref` and `wasm_func_t` * wasmtime-c-api: More ownership documentation for `wasmtime.h`
1 parent c3e8a04 commit a9455a8

File tree

4 files changed

+68
-9
lines changed

4 files changed

+68
-9
lines changed

crates/c-api/include/wasmtime.h

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -515,8 +515,7 @@ typedef own wasm_trap_t* (*wasmtime_func_callback_t)(const wasmtime_caller_t* ca
515515
*
516516
* This function is the same as #wasm_func_callback_with_env_t except that its
517517
* first argument is a #wasmtime_caller_t which allows learning information
518-
* about the
519-
* caller.
518+
* about the caller.
520519
*/
521520
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[]);
522521

@@ -544,6 +543,28 @@ WASM_API_EXTERN own wasm_func_t* wasmtime_func_new_with_env(
544543
void (*finalizer)(void*)
545544
);
546545

546+
/**
547+
* \brief Creates a new `funcref` value referencing `func`.
548+
*
549+
* Create a `funcref` value that references `func` and writes it to `funcrefp`.
550+
*
551+
* Gives ownership fo the `funcref` value written to `funcrefp`.
552+
*
553+
* Both `func` and `funcrefp` must not be NULL.
554+
*/
555+
WASM_API_EXTERN void wasmtime_func_as_funcref(const wasm_func_t* func, wasm_val_t* funcrefp);
556+
557+
/**
558+
* \brief Get the `wasm_func_t*` referenced by the given `funcref` value.
559+
*
560+
* Gets an owning handle to the `wasm_func_t*` that the given `funcref` value is
561+
* referencing. Returns NULL if the value is not a `funcref`, or if the value is
562+
* a null function reference.
563+
*
564+
* The `val` pointer must not be NULL.
565+
*/
566+
WASM_API_EXTERN own wasm_func_t* wasmtime_funcref_as_func(const wasm_val_t* val);
567+
547568
/**
548569
* \brief Loads a #wasm_extern_t from the caller's context
549570
*
@@ -845,8 +866,10 @@ WASM_API_EXTERN wasmtime_error_t *wasmtime_funcref_table_grow(
845866
* This function does not take an associated finalizer to clean up the data when
846867
* the reference is reclaimed. If you need a finalizer to clean up the data,
847868
* then use #wasmtime_externref_new_with_finalizer.
869+
*
870+
* Gives ownership of the newly created `externref` value.
848871
*/
849-
WASM_API_EXTERN void wasmtime_externref_new(void *data, wasm_val_t *valp);
872+
WASM_API_EXTERN void wasmtime_externref_new(own void *data, wasm_val_t *valp);
850873

851874
/**
852875
* \brief A finalizer for an `externref`'s wrapped data.
@@ -866,9 +889,11 @@ typedef void (*wasmtime_externref_finalizer_t)(void*);
866889
* When the reference is reclaimed, the wrapped data is cleaned up with the
867890
* provided finalizer. If you do not need to clean up the wrapped data, then use
868891
* #wasmtime_externref_new.
892+
*
893+
* Gives ownership of the newly created `externref` value.
869894
*/
870895
WASM_API_EXTERN void wasmtime_externref_new_with_finalizer(
871-
void *data,
896+
own void *data,
872897
wasmtime_externref_finalizer_t finalizer,
873898
wasm_val_t *valp
874899
);
@@ -887,7 +912,8 @@ WASM_API_EXTERN void wasmtime_externref_new_with_finalizer(
887912
* If the given value is not an `externref`, returns `false` and leaves `datap`
888913
* unmodified.
889914
*
890-
* Does not take ownership of `val`.
915+
* Does not take ownership of `val`. Does not give up ownership of the `void*`
916+
* data written to `datap`.
891917
*
892918
* Both `val` and `datap` must not be `NULL`.
893919
*/

crates/c-api/src/func.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::mem::MaybeUninit;
66
use std::panic::{self, AssertUnwindSafe};
77
use std::ptr;
88
use std::str;
9-
use wasmtime::{Caller, Extern, Func, Trap};
9+
use wasmtime::{Caller, Extern, Func, Trap, Val};
1010

1111
#[derive(Clone)]
1212
#[repr(transparent)]
@@ -275,3 +275,21 @@ pub extern "C" fn wasmtime_caller_export_get(
275275
let which = caller.caller.get_export(name)?;
276276
Some(Box::new(wasm_extern_t { which }))
277277
}
278+
279+
#[no_mangle]
280+
pub extern "C" fn wasmtime_func_as_funcref(
281+
func: &wasm_func_t,
282+
funcrefp: &mut MaybeUninit<wasm_val_t>,
283+
) {
284+
let funcref = wasm_val_t::from_val(Val::FuncRef(Some(func.func().clone())));
285+
crate::initialize(funcrefp, funcref);
286+
}
287+
288+
#[no_mangle]
289+
pub extern "C" fn wasmtime_funcref_as_func(val: &wasm_val_t) -> Option<Box<wasm_func_t>> {
290+
if let Val::FuncRef(Some(f)) = val.val() {
291+
Some(Box::new(f.into()))
292+
} else {
293+
None
294+
}
295+
}

crates/c-api/src/table.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ pub extern "C" fn wasm_table_get(
9191
index: wasm_table_size_t,
9292
) -> Option<Box<wasm_ref_t>> {
9393
let val = t.table().get(index)?;
94-
Some(val_into_ref(val).unwrap())
94+
val_into_ref(val)
9595
}
9696

9797
#[no_mangle]

crates/c-api/src/val.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ impl Drop for wasm_val_t {
2626
fn drop(&mut self) {
2727
match into_valtype(self.kind) {
2828
ValType::ExternRef => unsafe {
29-
drop(Box::from_raw(self.of.ref_));
29+
if !self.of.ref_.is_null() {
30+
drop(Box::from_raw(self.of.ref_));
31+
}
3032
},
3133
_ => {}
3234
}
@@ -116,7 +118,20 @@ impl wasm_val_t {
116118
ValType::I64 => Val::from(unsafe { self.of.i64 }),
117119
ValType::F32 => Val::from(unsafe { self.of.f32 }),
118120
ValType::F64 => Val::from(unsafe { self.of.f64 }),
119-
ValType::ExternRef | ValType::FuncRef => ref_to_val(unsafe { &*self.of.ref_ }),
121+
ValType::ExternRef => unsafe {
122+
if self.of.ref_.is_null() {
123+
Val::ExternRef(None)
124+
} else {
125+
ref_to_val(&*self.of.ref_)
126+
}
127+
},
128+
ValType::FuncRef => unsafe {
129+
if self.of.ref_.is_null() {
130+
Val::FuncRef(None)
131+
} else {
132+
ref_to_val(&*self.of.ref_)
133+
}
134+
},
120135
_ => unimplemented!("wasm_val_t::val {:?}", self.kind),
121136
}
122137
}

0 commit comments

Comments
 (0)