mirror of
https://github.com/fluencelabs/wasmer
synced 2025-03-16 16:20:49 +00:00
Add WASI support to runtime-c-api
This commit is contained in:
parent
b74e62af3d
commit
b45b1c12f1
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1639,6 +1639,7 @@ dependencies = [
|
||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasmer-runtime 0.7.0",
|
||||
"wasmer-runtime-core 0.7.0",
|
||||
"wasmer-wasi 0.7.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -24,12 +24,19 @@ default-features = false
|
||||
path = "../runtime-core"
|
||||
version = "0.7.0"
|
||||
|
||||
[dependencies.wasmer-wasi]
|
||||
default-features = false
|
||||
path = "../wasi"
|
||||
version = "0.7.0"
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
default = ["cranelift-backend"]
|
||||
default = ["cranelift-backend", "wasi"]
|
||||
debug = ["wasmer-runtime/debug"]
|
||||
cranelift-backend = ["wasmer-runtime/cranelift", "wasmer-runtime/default-backend-cranelift"]
|
||||
llvm-backend = ["wasmer-runtime/llvm", "wasmer-runtime/default-backend-llvm"]
|
||||
singlepass-backend = ["wasmer-runtime/singlepass", "wasmer-runtime/default-backend-singlepass"]
|
||||
wasi = ["wasmer-wasi"]
|
||||
|
||||
[build-dependencies]
|
||||
cbindgen = "0.9"
|
||||
|
@ -51,6 +51,110 @@ pub unsafe extern "C" fn wasmer_import_object_new() -> *mut wasmer_import_object
|
||||
Box::into_raw(import_object) as *mut wasmer_import_object_t
|
||||
}
|
||||
|
||||
#[cfg(feature = "wasi")]
|
||||
mod wasi {
|
||||
use super::*;
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Opens a directory that's visible to the WASI module as `alias` but
|
||||
/// is backed by the host file at `host_file_path`
|
||||
#[repr(C)]
|
||||
pub struct wasmer_wasi_map_dir_entry_t {
|
||||
/// What the WASI module will see in its virtual root
|
||||
pub alias: wasmer_byte_array,
|
||||
/// The backing file that the WASI module will interact with via the alias
|
||||
pub host_file_path: wasmer_byte_array,
|
||||
}
|
||||
|
||||
impl wasmer_wasi_map_dir_entry_t {
|
||||
/// Converts the data into owned, Rust types
|
||||
pub unsafe fn as_tuple(&self) -> Result<(String, PathBuf), std::str::Utf8Error> {
|
||||
let alias = self.alias.as_str()?.to_owned();
|
||||
let host_path = std::path::PathBuf::from(self.host_file_path.as_str()?);
|
||||
|
||||
Ok((alias, host_path))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a WASI import object
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmer_wasi_generate_import_object(
|
||||
args: *const wasmer_byte_array,
|
||||
args_len: c_uint,
|
||||
envs: *const wasmer_byte_array,
|
||||
envs_len: c_uint,
|
||||
preopened_files: *const wasmer_byte_array,
|
||||
preopened_files_len: c_uint,
|
||||
mapped_dirs: *const wasmer_wasi_map_dir_entry_t,
|
||||
mapped_dirs_len: c_uint,
|
||||
) -> *mut wasmer_import_object_t {
|
||||
let arg_list = std::slice::from_raw_parts(args, args_len as usize);
|
||||
let env_list = std::slice::from_raw_parts(envs, envs_len as usize);
|
||||
let preopened_file_list =
|
||||
std::slice::from_raw_parts(preopened_files, preopened_files_len as usize);
|
||||
let mapped_dir_list = std::slice::from_raw_parts(mapped_dirs, mapped_dirs_len as usize);
|
||||
|
||||
wasmer_wasi_generate_import_object_inner(
|
||||
arg_list,
|
||||
env_list,
|
||||
preopened_file_list,
|
||||
mapped_dir_list,
|
||||
)
|
||||
.unwrap_or(std::ptr::null_mut())
|
||||
}
|
||||
|
||||
/// Inner function that wraps error handling
|
||||
fn wasmer_wasi_generate_import_object_inner(
|
||||
arg_list: &[wasmer_byte_array],
|
||||
env_list: &[wasmer_byte_array],
|
||||
preopened_file_list: &[wasmer_byte_array],
|
||||
mapped_dir_list: &[wasmer_wasi_map_dir_entry_t],
|
||||
) -> Result<*mut wasmer_import_object_t, std::str::Utf8Error> {
|
||||
let arg_vec = arg_list.iter().map(|arg| unsafe { arg.as_vec() }).collect();
|
||||
let env_vec = env_list
|
||||
.iter()
|
||||
.map(|env_var| unsafe { env_var.as_vec() })
|
||||
.collect();
|
||||
let po_file_vec = preopened_file_list
|
||||
.iter()
|
||||
.map(|po_file| Ok(unsafe { po_file.as_str()? }.to_owned()))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let mapped_dir_vec = mapped_dir_list
|
||||
.iter()
|
||||
.map(|entry| unsafe { entry.as_tuple() })
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let import_object = Box::new(wasmer_wasi::generate_import_object(
|
||||
arg_vec,
|
||||
env_vec,
|
||||
po_file_vec,
|
||||
mapped_dir_vec,
|
||||
));
|
||||
Ok(Box::into_raw(import_object) as *mut wasmer_import_object_t)
|
||||
}
|
||||
|
||||
/// Convenience function that creates a WASI import object with no arguments,
|
||||
/// environment variables, preopened files, or mapped directories.
|
||||
///
|
||||
/// This function is the same as calling [`wasmer_wasi_generate_import_object`] with all
|
||||
/// empty values.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmer_wasi_generate_default_import_object(
|
||||
) -> *mut wasmer_import_object_t {
|
||||
let import_object = Box::new(wasmer_wasi::generate_import_object(
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
vec![],
|
||||
));
|
||||
|
||||
Box::into_raw(import_object) as *mut wasmer_import_object_t
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "wasi")]
|
||||
pub use self::wasi::*;
|
||||
|
||||
/// Extends an existing import object with new imports
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
#[no_mangle]
|
||||
|
@ -129,3 +129,23 @@ pub struct wasmer_byte_array {
|
||||
pub bytes: *const u8,
|
||||
pub bytes_len: u32,
|
||||
}
|
||||
|
||||
impl wasmer_byte_array {
|
||||
/// Get the data as a slice
|
||||
pub unsafe fn as_slice<'a>(&self) -> &'a [u8] {
|
||||
std::slice::from_raw_parts(self.bytes, self.bytes_len as usize)
|
||||
}
|
||||
|
||||
/// Copy the data into an owned Vec
|
||||
pub unsafe fn as_vec(&self) -> Vec<u8> {
|
||||
let mut out = Vec::with_capacity(self.bytes_len as usize);
|
||||
out.extend_from_slice(self.as_slice());
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
/// Read the data as a &str, returns an error if the string is not valid UTF8
|
||||
pub unsafe fn as_str<'a>(&self) -> Result<&'a str, std::str::Utf8Error> {
|
||||
std::str::from_utf8(self.as_slice())
|
||||
}
|
||||
}
|
||||
|
@ -170,6 +170,21 @@ typedef struct {
|
||||
|
||||
} wasmer_trampoline_buffer_t;
|
||||
|
||||
/**
|
||||
* Opens a directory that's visible to the WASI module as `alias` but
|
||||
* is backed by the host file at `host_file_path`
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* What the WASI module will see in its virtual root
|
||||
*/
|
||||
wasmer_byte_array alias;
|
||||
/**
|
||||
* The backing file that the WASI module will interact with via the alias
|
||||
*/
|
||||
wasmer_byte_array host_file_path;
|
||||
} wasmer_wasi_map_dir_entry_t;
|
||||
|
||||
/**
|
||||
* Creates a new Module from the given wasm bytes.
|
||||
*
|
||||
@ -756,4 +771,25 @@ void *wasmer_trampoline_get_context(void);
|
||||
*/
|
||||
bool wasmer_validate(const uint8_t *wasm_bytes, uint32_t wasm_bytes_len);
|
||||
|
||||
/**
|
||||
* Convenience function that creates a WASI import object with no arguments,
|
||||
* environment variables, preopened files, or mapped directories.
|
||||
*
|
||||
* This function is the same as calling [`wasmer_wasi_generate_import_object`] with all
|
||||
* empty values.
|
||||
*/
|
||||
wasmer_import_object_t *wasmer_wasi_generate_default_import_object(void);
|
||||
|
||||
/**
|
||||
* Creates a WASI import object
|
||||
*/
|
||||
wasmer_import_object_t *wasmer_wasi_generate_import_object(const wasmer_byte_array *args,
|
||||
unsigned int args_len,
|
||||
const wasmer_byte_array *envs,
|
||||
unsigned int envs_len,
|
||||
const wasmer_byte_array *preopened_files,
|
||||
unsigned int preopened_files_len,
|
||||
const wasmer_wasi_map_dir_entry_t *mapped_dirs,
|
||||
unsigned int mapped_dirs_len);
|
||||
|
||||
#endif /* WASMER_H */
|
||||
|
@ -154,6 +154,15 @@ struct wasmer_trampoline_buffer_t {
|
||||
|
||||
};
|
||||
|
||||
/// Opens a directory that's visible to the WASI module as `alias` but
|
||||
/// is backed by the host file at `host_file_path`
|
||||
struct wasmer_wasi_map_dir_entry_t {
|
||||
/// What the WASI module will see in its virtual root
|
||||
wasmer_byte_array alias;
|
||||
/// The backing file that the WASI module will interact with via the alias
|
||||
wasmer_byte_array host_file_path;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
/// Creates a new Module from the given wasm bytes.
|
||||
@ -590,6 +599,23 @@ void *wasmer_trampoline_get_context();
|
||||
/// Returns true for valid wasm bytes and false for invalid bytes
|
||||
bool wasmer_validate(const uint8_t *wasm_bytes, uint32_t wasm_bytes_len);
|
||||
|
||||
/// Convenience function that creates a WASI import object with no arguments,
|
||||
/// environment variables, preopened files, or mapped directories.
|
||||
///
|
||||
/// This function is the same as calling [`wasmer_wasi_generate_import_object`] with all
|
||||
/// empty values.
|
||||
wasmer_import_object_t *wasmer_wasi_generate_default_import_object();
|
||||
|
||||
/// Creates a WASI import object
|
||||
wasmer_import_object_t *wasmer_wasi_generate_import_object(const wasmer_byte_array *args,
|
||||
unsigned int args_len,
|
||||
const wasmer_byte_array *envs,
|
||||
unsigned int envs_len,
|
||||
const wasmer_byte_array *preopened_files,
|
||||
unsigned int preopened_files_len,
|
||||
const wasmer_wasi_map_dir_entry_t *mapped_dirs,
|
||||
unsigned int mapped_dirs_len);
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#endif // WASMER_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user