Skip to content

Commit

Permalink
C API support.
Browse files Browse the repository at this point in the history
  • Loading branch information
sunfishcode committed May 22, 2020
1 parent 39c46d4 commit b9b912c
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 21 deletions.
12 changes: 12 additions & 0 deletions crates/c-api/include/wasmtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,18 @@ WASM_API_EXTERN own wasmtime_error_t* wasmtime_linker_instantiate(
own wasm_trap_t **trap
);

WASM_API_EXTERN own wasmtime_error_t* wasmtime_linker_module(
const wasmtime_linker_t *linker,
const wasm_name_t *name,
const wasm_module_t *module
);

WASM_API_EXTERN own wasmtime_error_t* wasmtime_linker_get_default(
const wasmtime_linker_t *linker,
const wasm_name_t *name,
own wasm_func_t **func
);

///////////////////////////////////////////////////////////////////////////////
//
// wasmtime_caller_t extension, binding the `Caller` type in the Rust API
Expand Down
34 changes: 32 additions & 2 deletions crates/c-api/src/linker.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::{bad_utf8, handle_result, wasmtime_error_t};
use crate::{wasm_extern_t, wasm_store_t, ExternHost};
use crate::{wasm_instance_t, wasm_module_t, wasm_name_t, wasm_trap_t};
use crate::{wasm_func_t, wasm_instance_t, wasm_module_t, wasm_name_t, wasm_trap_t};
use std::str;
use wasmtime::{Extern, Linker};
use wasmtime::{Extern, HostRef, Linker};

#[repr(C)]
pub struct wasmtime_linker_t {
Expand Down Expand Up @@ -89,3 +89,33 @@ pub unsafe extern "C" fn wasmtime_linker_instantiate(
let result = linker.linker.instantiate(&module.module.borrow());
super::instance::handle_instantiate(result, instance_ptr, trap_ptr)
}

#[no_mangle]
pub unsafe extern "C" fn wasmtime_linker_module(
linker: &mut wasmtime_linker_t,
name: &wasm_name_t,
module: &wasm_module_t,
) -> Option<Box<wasmtime_error_t>> {
let linker = &mut linker.linker;
let name = match str::from_utf8(name.as_slice()) {
Ok(s) => s,
Err(_) => return bad_utf8(),
};
handle_result(linker.module(name, &module.module.borrow()), |_linker| ())
}

#[no_mangle]
pub unsafe extern "C" fn wasmtime_linker_get_default(
linker: &mut wasmtime_linker_t,
name: &wasm_name_t,
func: &mut *mut wasm_func_t,
) -> Option<Box<wasmtime_error_t>> {
let linker = &mut linker.linker;
let name = match str::from_utf8(name.as_slice()) {
Ok(s) => s,
Err(_) => return bad_utf8(),
};
handle_result(linker.get_default(name), |f| {
*func = Box::into_raw(Box::new(HostRef::new(f).into()))
})
}
38 changes: 19 additions & 19 deletions examples/wasi/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,30 +72,30 @@ int main() {
if (wasi == NULL)
exit_with_error("failed to instantiate WASI", NULL, trap);

// Create import list for our module using wasi
wasm_importtype_vec_t import_types;
wasm_module_imports(module, &import_types);
const wasm_extern_t **imports = calloc(import_types.size, sizeof(void*));
assert(imports);
for (int i = 0; i < import_types.size; i++) {
const wasm_extern_t *binding = wasi_instance_bind_import(wasi, import_types.data[i]);
if (binding != NULL) {
imports[i] = binding;
} else {
printf("> Failed to satisfy import\n");
exit(1);
}
}
wasmtime_linker_t *linker = wasmtime_linker_new(store);
error = wasmtime_linker_define_wasi(linker, wasi);
if (error != NULL)
exit_with_error("failed to link wasi", error, NULL);

// Instantiate the module
wasm_name_t empty;
wasm_name_new_from_string(&empty, "");
wasm_instance_t *instance = NULL;
error = wasmtime_instance_new(module, imports, import_types.size, &instance, &trap);
if (instance == NULL)
exit_with_error("failed to run command", error, trap);
free(imports);
wasm_importtype_vec_delete(&import_types);
error = wasmtime_linker_module(linker, &empty, module);
if (error != NULL)
exit_with_error("failed to instantiate module", error, NULL);

// Run it.
wasm_func_t* func;
wasmtime_linker_get_default(linker, &empty, &func);
if (error != NULL)
exit_with_error("failed to locate default export for module", error, NULL);
error = wasmtime_func_call(func, NULL, 0, NULL, 0, &trap);
if (error != NULL)
exit_with_error("error calling default export", error, trap);

// Clean up after ourselves at this point
wasm_name_delete(&empty);
wasm_module_delete(module);
wasm_store_delete(store);
wasm_engine_delete(engine);
Expand Down

0 comments on commit b9b912c

Please sign in to comment.