mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-12 13:28:49 +00:00
Make caller responsible for allocation array for getting WASI imports
This commit is contained in:
@@ -17,9 +17,9 @@ use crate::c_try;
|
||||
|
||||
use crate::ordered_resolver::OrderedResolver;
|
||||
use wasmer::{
|
||||
Engine, ExportType, Extern, ExternType, Function, FunctionType, Global, GlobalType, Instance,
|
||||
Memory, MemoryType, Module, Mutability, Pages, RuntimeError, Store, Table, TableType, Val,
|
||||
ValType,
|
||||
Engine, ExportType, Extern, ExternType, Function, FunctionType, Global, GlobalType, ImportType,
|
||||
Instance, Memory, MemoryType, Module, Mutability, Pages, RuntimeError, Store, Table, TableType,
|
||||
Val, ValType,
|
||||
};
|
||||
#[cfg(feature = "jit")]
|
||||
use wasmer_engine_jit::JIT;
|
||||
@@ -230,6 +230,25 @@ pub unsafe extern "C" fn wasm_module_exports(
|
||||
mem::forget(exports);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_module_imports(
|
||||
module: &wasm_module_t,
|
||||
out: &mut wasm_importtype_vec_t,
|
||||
) {
|
||||
let mut imports = module
|
||||
.inner
|
||||
.imports()
|
||||
.map(Into::into)
|
||||
.map(Box::new)
|
||||
.map(Box::into_raw)
|
||||
.collect::<Vec<*mut wasm_importtype_t>>();
|
||||
|
||||
debug_assert_eq!(imports.len(), imports.capacity());
|
||||
out.size = imports.len();
|
||||
out.data = imports.as_mut_ptr();
|
||||
mem::forget(imports);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasm_module_deserialize(
|
||||
store_ptr: Option<NonNull<wasm_store_t>>,
|
||||
@@ -1808,3 +1827,91 @@ impl From<&ExportType> for wasm_exporttype_t {
|
||||
wasm_exporttype_t { name, extern_type }
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: improve ownership in `importtype_t` (can we safely use `Box<wasm_name_t>` here?)
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct wasm_importtype_t {
|
||||
module: NonNull<wasm_name_t>,
|
||||
name: NonNull<wasm_name_t>,
|
||||
extern_type: NonNull<wasm_externtype_t>,
|
||||
}
|
||||
|
||||
wasm_declare_boxed_vec!(importtype);
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_importtype_new(
|
||||
module: NonNull<wasm_name_t>,
|
||||
name: NonNull<wasm_name_t>,
|
||||
extern_type: NonNull<wasm_externtype_t>,
|
||||
) -> Box<wasm_importtype_t> {
|
||||
Box::new(wasm_importtype_t {
|
||||
name,
|
||||
module,
|
||||
extern_type,
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_importtype_module(et: &'static wasm_importtype_t) -> &'static wasm_name_t {
|
||||
unsafe { et.module.as_ref() }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_importtype_name(et: &'static wasm_importtype_t) -> &'static wasm_name_t {
|
||||
unsafe { et.name.as_ref() }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wasm_importtype_type(
|
||||
et: &'static wasm_importtype_t,
|
||||
) -> &'static wasm_externtype_t {
|
||||
unsafe { et.extern_type.as_ref() }
|
||||
}
|
||||
|
||||
impl From<ImportType> for wasm_importtype_t {
|
||||
fn from(other: ImportType) -> Self {
|
||||
(&other).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ImportType> for wasm_importtype_t {
|
||||
fn from(other: &ImportType) -> Self {
|
||||
// TODO: double check that freeing String as `Vec<u8>` is valid
|
||||
let name = {
|
||||
let mut heap_str: Box<str> = other.name().to_string().into_boxed_str();
|
||||
let char_ptr = heap_str.as_mut_ptr();
|
||||
let str_len = heap_str.bytes().len();
|
||||
let name_inner = wasm_name_t {
|
||||
size: str_len,
|
||||
data: char_ptr,
|
||||
};
|
||||
Box::leak(heap_str);
|
||||
unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(name_inner))) }
|
||||
};
|
||||
|
||||
// TODO: double check that freeing String as `Vec<u8>` is valid
|
||||
let module = {
|
||||
let mut heap_str: Box<str> = other.module().to_string().into_boxed_str();
|
||||
let char_ptr = heap_str.as_mut_ptr();
|
||||
let str_len = heap_str.bytes().len();
|
||||
let name_inner = wasm_name_t {
|
||||
size: str_len,
|
||||
data: char_ptr,
|
||||
};
|
||||
Box::leak(heap_str);
|
||||
unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(name_inner))) }
|
||||
};
|
||||
|
||||
let extern_type = {
|
||||
let extern_type: wasm_externtype_t = other.ty().into();
|
||||
unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(extern_type))) }
|
||||
};
|
||||
|
||||
wasm_importtype_t {
|
||||
name,
|
||||
module,
|
||||
extern_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +228,18 @@ pub unsafe extern "C" fn wasi_get_imports(
|
||||
store: Option<NonNull<wasm_store_t>>,
|
||||
module: &wasm_module_t,
|
||||
wasi_env: &wasi_env_t,
|
||||
) -> Option<Box<[Box<wasm_extern_t>]>> {
|
||||
imports: *mut *mut wasm_extern_t,
|
||||
) -> bool {
|
||||
wasi_get_imports_inner(store, module, wasi_env, imports).is_some()
|
||||
}
|
||||
|
||||
/// Takes ownership of `wasi_env_t`.
|
||||
unsafe extern "C" fn wasi_get_imports_inner(
|
||||
store: Option<NonNull<wasm_store_t>>,
|
||||
module: &wasm_module_t,
|
||||
wasi_env: &wasi_env_t,
|
||||
imports: *mut *mut wasm_extern_t,
|
||||
) -> Option<()> {
|
||||
let store_ptr = store?.cast::<Store>();
|
||||
let store = store_ptr.as_ref();
|
||||
|
||||
@@ -240,8 +251,7 @@ pub unsafe extern "C" fn wasi_get_imports(
|
||||
|
||||
let import_object = generate_import_object_from_env(store, wasi_env.inner.clone(), version);
|
||||
|
||||
let mut extern_vec = vec![];
|
||||
for it in module.inner.imports() {
|
||||
for (i, it) in module.inner.imports().enumerate() {
|
||||
let export = c_try!(import_object
|
||||
.resolve_by_name(it.module(), it.name())
|
||||
.ok_or_else(|| CApiError {
|
||||
@@ -252,11 +262,15 @@ pub unsafe extern "C" fn wasi_get_imports(
|
||||
),
|
||||
}));
|
||||
let inner = Extern::from_export(store, export);
|
||||
extern_vec.push(Box::new(wasm_extern_t {
|
||||
*imports.add(i) = Box::into_raw(Box::new(wasm_extern_t {
|
||||
instance: None,
|
||||
inner,
|
||||
}));
|
||||
}
|
||||
|
||||
Some(extern_vec.into_boxed_slice())
|
||||
Some(())
|
||||
}
|
||||
|
||||
/// Delete a `wasm_extern_t` allocated by the API.
|
||||
#[no_mangle]
|
||||
pub unsafe fn wasm_extern_delete(_item: Option<Box<wasm_extern_t>>) {}
|
||||
|
||||
@@ -69,14 +69,20 @@ int main(int argc, const char* argv[]) {
|
||||
|
||||
// Instantiate.
|
||||
printf("Instantiating module...\n");
|
||||
const wasm_extern_t* const* imports = wasi_get_imports(store, module, wasi_env);
|
||||
if (!imports) {
|
||||
wasm_importtype_vec_t import_types;
|
||||
wasm_module_imports(module, &import_types);
|
||||
int num_imports = import_types.size;
|
||||
wasm_extern_t** imports = malloc(num_imports * sizeof(wasm_extern_t*));
|
||||
wasm_importtype_vec_delete(&import_types);
|
||||
|
||||
bool get_imports_result = wasi_get_imports(store, module, wasi_env, imports);
|
||||
if (!get_imports_result) {
|
||||
printf("> Error getting WASI imports!\n");
|
||||
print_wasmer_error();
|
||||
return 1;
|
||||
}
|
||||
own wasm_instance_t* instance =
|
||||
wasm_instance_new(store, module, imports, NULL);
|
||||
wasm_instance_new(store, module, (const wasm_extern_t *const *) imports, NULL);
|
||||
if (!instance) {
|
||||
printf("> Error instantiating module!\n");
|
||||
print_wasmer_error();
|
||||
@@ -131,6 +137,12 @@ int main(int argc, const char* argv[]) {
|
||||
|
||||
wasm_extern_vec_delete(&exports);
|
||||
|
||||
// NEEDS REVIEW:
|
||||
for(int i = 0; i < num_imports; ++i) {
|
||||
wasm_extern_delete(imports[i]);
|
||||
}
|
||||
free(imports);
|
||||
|
||||
// Shut down.
|
||||
printf("Shutting down...\n");
|
||||
wasi_env_delete(wasi_env);
|
||||
|
||||
@@ -63,9 +63,10 @@ own wasi_env_t* wasi_env_new(own wasi_config_t*);
|
||||
void wasi_env_delete(own wasi_env_t*);
|
||||
|
||||
// Get an array of imports that can be used to instantiate the given module.
|
||||
own const wasm_extern_t* own const* wasi_get_imports(wasm_store_t* store,
|
||||
bool wasi_get_imports(wasm_store_t* store,
|
||||
wasm_module_t* module,
|
||||
wasi_env_t* wasi_env);
|
||||
wasi_env_t* wasi_env,
|
||||
wasm_extern_t** imports);
|
||||
|
||||
// TODO: investigate removing this part of the API
|
||||
// Set the memory in the `wasi_env_t` so that the WASI host functions can access WASI's memory.
|
||||
@@ -86,6 +87,9 @@ size_t wasi_env_read_stderr(wasi_env_t* env,
|
||||
// Get the version of WASI needed by the given Wasm module.
|
||||
wasi_version_t wasi_get_wasi_version(wasm_module_t*);
|
||||
|
||||
// Delete a `wasm_extern_t` allocated by the API.
|
||||
void wasm_extern_delete(wasm_extern_t*);
|
||||
|
||||
// TODO: figure out if we can do less duplication.
|
||||
/**
|
||||
* Gets the length in bytes of the last error if any.
|
||||
|
||||
Reference in New Issue
Block a user