Implement WASI C API.
This commit implements an initial WASI C API that can be used to instantiate and configure a WASI instance from C. This also implements a `WasiBuilder` for the C# API enabling .NET hosts to bind to Wasmtime's WASI implementation.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,3 +10,4 @@ rusty-tags.*
|
|||||||
*~
|
*~
|
||||||
\#*\#
|
\#*\#
|
||||||
docs/book
|
docs/book
|
||||||
|
.vscode/
|
||||||
|
|||||||
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -1990,7 +1990,9 @@ dependencies = [
|
|||||||
name = "wasmtime-c-api"
|
name = "wasmtime-c-api"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"wasi-common",
|
||||||
"wasmtime",
|
"wasmtime",
|
||||||
|
"wasmtime-wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -18,3 +18,5 @@ doctest = false
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmtime = { path = "../api" }
|
wasmtime = { path = "../api" }
|
||||||
|
wasi-common = { path = "../wasi-common" }
|
||||||
|
wasmtime-wasi = { path = "../wasi" }
|
||||||
|
|||||||
70
crates/c-api/include/wasi.h
Normal file
70
crates/c-api/include/wasi.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
// WASI C API
|
||||||
|
|
||||||
|
#ifndef WASI_H
|
||||||
|
#define WASI_H
|
||||||
|
|
||||||
|
#include "wasm.h"
|
||||||
|
|
||||||
|
#ifndef WASI_API_EXTERN
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define WASI_API_EXTERN __declspec(dllimport)
|
||||||
|
#else
|
||||||
|
#define WASI_API_EXTERN
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define own
|
||||||
|
|
||||||
|
#define WASI_DECLARE_OWN(name) \
|
||||||
|
typedef struct wasi_##name##_t wasi_##name##_t; \
|
||||||
|
WASI_API_EXTERN void wasi_##name##_delete(own wasi_##name##_t*);
|
||||||
|
|
||||||
|
// WASI config
|
||||||
|
|
||||||
|
WASI_DECLARE_OWN(config)
|
||||||
|
|
||||||
|
WASI_API_EXTERN own wasi_config_t* wasi_config_new();
|
||||||
|
|
||||||
|
WASI_API_EXTERN void wasi_config_set_argv(wasi_config_t* config, int argc, const char* argv[]);
|
||||||
|
WASI_API_EXTERN void wasi_config_inherit_argv(wasi_config_t* config);
|
||||||
|
|
||||||
|
WASI_API_EXTERN void wasi_config_set_env(wasi_config_t* config, int envc, const char* names[], const char* values[]);
|
||||||
|
WASI_API_EXTERN void wasi_config_inherit_env(wasi_config_t* config);
|
||||||
|
|
||||||
|
WASI_API_EXTERN bool wasi_config_set_stdin(wasi_config_t* config, const char* path);
|
||||||
|
WASI_API_EXTERN void wasi_config_inherit_stdin(wasi_config_t* config);
|
||||||
|
|
||||||
|
WASI_API_EXTERN bool wasi_config_set_stdout(wasi_config_t* config, const char* path);
|
||||||
|
WASI_API_EXTERN void wasi_config_inherit_stdout(wasi_config_t* config);
|
||||||
|
|
||||||
|
WASI_API_EXTERN bool wasi_config_set_stderr(wasi_config_t* config, const char* path);
|
||||||
|
WASI_API_EXTERN void wasi_config_inherit_stderr(wasi_config_t* config);
|
||||||
|
|
||||||
|
WASI_API_EXTERN bool wasi_config_preopen_dir(wasi_config_t* config, const char* path, const char* guest_path);
|
||||||
|
|
||||||
|
// WASI instance
|
||||||
|
|
||||||
|
WASI_DECLARE_OWN(instance)
|
||||||
|
|
||||||
|
WASI_API_EXTERN own wasi_instance_t* wasi_instance_new(
|
||||||
|
wasm_store_t* store,
|
||||||
|
own wasi_config_t* config,
|
||||||
|
own wasm_trap_t** trap
|
||||||
|
);
|
||||||
|
|
||||||
|
WASI_API_EXTERN const wasm_extern_t* wasi_instance_bind_import(
|
||||||
|
const wasi_instance_t* instance,
|
||||||
|
const wasm_importtype_t* import
|
||||||
|
);
|
||||||
|
|
||||||
|
#undef own
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // #ifdef WASI_H
|
||||||
@@ -15,6 +15,12 @@ use wasmtime::{
|
|||||||
Table, TableType, Trap, Val, ValType,
|
Table, TableType, Trap, Val, ValType,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod ext;
|
||||||
|
mod wasi;
|
||||||
|
|
||||||
|
pub use crate::ext::*;
|
||||||
|
pub use crate::wasi::*;
|
||||||
|
|
||||||
macro_rules! declare_vec {
|
macro_rules! declare_vec {
|
||||||
($name:ident, $elem_ty:path) => {
|
($name:ident, $elem_ty:path) => {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@@ -1025,7 +1031,7 @@ pub unsafe extern "C" fn wasm_trap_new(
|
|||||||
if message[message.len() - 1] != 0 {
|
if message[message.len() - 1] != 0 {
|
||||||
panic!("wasm_trap_new message stringz expected");
|
panic!("wasm_trap_new message stringz expected");
|
||||||
}
|
}
|
||||||
let message = String::from_utf8_lossy(message);
|
let message = String::from_utf8_lossy(&message[..message.len() - 1]);
|
||||||
let trap = Box::new(wasm_trap_t {
|
let trap = Box::new(wasm_trap_t {
|
||||||
trap: HostRef::new(Trap::new(message)),
|
trap: HostRef::new(Trap::new(message)),
|
||||||
});
|
});
|
||||||
@@ -1777,7 +1783,3 @@ pub unsafe extern "C" fn wasm_valtype_vec_copy(
|
|||||||
let slice = slice::from_raw_parts((*src).data, (*src).size);
|
let slice = slice::from_raw_parts((*src).data, (*src).size);
|
||||||
(*out).set_from_slice(slice);
|
(*out).set_from_slice(slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
mod ext;
|
|
||||||
|
|
||||||
pub use crate::ext::*;
|
|
||||||
|
|||||||
274
crates/c-api/src/wasi.rs
Normal file
274
crates/c-api/src/wasi.rs
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
//! The WASI embedding API definitions for Wasmtime.
|
||||||
|
use crate::{wasm_extern_t, wasm_importtype_t, wasm_store_t, wasm_trap_t, ExternHost, ExternType};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::ffi::CStr;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::os::raw::{c_char, c_int};
|
||||||
|
use std::path::Path;
|
||||||
|
use std::slice;
|
||||||
|
use wasi_common::{preopen_dir, WasiCtxBuilder};
|
||||||
|
use wasmtime::{HostRef, Trap};
|
||||||
|
use wasmtime_wasi::Wasi;
|
||||||
|
|
||||||
|
unsafe fn cstr_to_path<'a>(path: *const c_char) -> Option<&'a Path> {
|
||||||
|
CStr::from_ptr(path).to_str().map(Path::new).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn open_file(path: *const c_char) -> Option<File> {
|
||||||
|
File::open(cstr_to_path(path)?).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn create_file(path: *const c_char) -> Option<File> {
|
||||||
|
File::create(cstr_to_path(path)?).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct wasi_config_t {
|
||||||
|
builder: WasiCtxBuilder,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl wasi_config_t {}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasi_config_new() -> *mut wasi_config_t {
|
||||||
|
Box::into_raw(Box::new(wasi_config_t {
|
||||||
|
builder: WasiCtxBuilder::new(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasi_config_delete(config: *mut wasi_config_t) {
|
||||||
|
drop(Box::from_raw(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasi_config_set_argv(
|
||||||
|
config: *mut wasi_config_t,
|
||||||
|
argc: c_int,
|
||||||
|
argv: *const *const c_char,
|
||||||
|
) {
|
||||||
|
let mut config = Box::from_raw(config);
|
||||||
|
config.builder = config.builder.args(
|
||||||
|
slice::from_raw_parts(argv, argc as usize)
|
||||||
|
.iter()
|
||||||
|
.map(|a| slice::from_raw_parts(*a as *const u8, CStr::from_ptr(*a).to_bytes().len())),
|
||||||
|
);
|
||||||
|
std::mem::forget(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasi_config_inherit_argv(config: *mut wasi_config_t) {
|
||||||
|
let mut config = Box::from_raw(config);
|
||||||
|
config.builder = config.builder.inherit_args();
|
||||||
|
std::mem::forget(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasi_config_set_env(
|
||||||
|
config: *mut wasi_config_t,
|
||||||
|
envc: c_int,
|
||||||
|
names: *const *const c_char,
|
||||||
|
values: *const *const c_char,
|
||||||
|
) {
|
||||||
|
let names = slice::from_raw_parts(names, envc as usize);
|
||||||
|
let values = slice::from_raw_parts(values, envc as usize);
|
||||||
|
let mut config = Box::from_raw(config);
|
||||||
|
|
||||||
|
for i in 0..envc as usize {
|
||||||
|
config.builder = config.builder.env(
|
||||||
|
CStr::from_ptr(names[i]).to_bytes(),
|
||||||
|
CStr::from_ptr(values[i]).to_bytes(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::mem::forget(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasi_config_inherit_env(config: *mut wasi_config_t) {
|
||||||
|
let mut config = Box::from_raw(config);
|
||||||
|
config.builder = config.builder.inherit_env();
|
||||||
|
std::mem::forget(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasi_config_set_stdin(
|
||||||
|
config: *mut wasi_config_t,
|
||||||
|
path: *const c_char,
|
||||||
|
) -> bool {
|
||||||
|
let file = match open_file(path) {
|
||||||
|
Some(f) => f,
|
||||||
|
None => return false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut config = Box::from_raw(config);
|
||||||
|
config.builder = config.builder.stdin(file);
|
||||||
|
std::mem::forget(config);
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasi_config_inherit_stdin(config: *mut wasi_config_t) {
|
||||||
|
let mut config = Box::from_raw(config);
|
||||||
|
config.builder = config.builder.inherit_stdin();
|
||||||
|
std::mem::forget(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasi_config_set_stdout(
|
||||||
|
config: *mut wasi_config_t,
|
||||||
|
path: *const c_char,
|
||||||
|
) -> bool {
|
||||||
|
let file = match create_file(path) {
|
||||||
|
Some(f) => f,
|
||||||
|
None => return false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut config = Box::from_raw(config);
|
||||||
|
config.builder = config.builder.stdout(file);
|
||||||
|
std::mem::forget(config);
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasi_config_inherit_stdout(config: *mut wasi_config_t) {
|
||||||
|
let mut config = Box::from_raw(config);
|
||||||
|
config.builder = config.builder.inherit_stdout();
|
||||||
|
std::mem::forget(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasi_config_set_stderr(
|
||||||
|
config: *mut wasi_config_t,
|
||||||
|
path: *const c_char,
|
||||||
|
) -> bool {
|
||||||
|
let file = match create_file(path) {
|
||||||
|
Some(f) => f,
|
||||||
|
None => return false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut config = Box::from_raw(config);
|
||||||
|
config.builder = config.builder.stderr(file);
|
||||||
|
std::mem::forget(config);
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasi_config_inherit_stderr(config: *mut wasi_config_t) {
|
||||||
|
let mut config = Box::from_raw(config);
|
||||||
|
config.builder = config.builder.inherit_stderr();
|
||||||
|
std::mem::forget(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasi_config_preopen_dir(
|
||||||
|
config: *mut wasi_config_t,
|
||||||
|
path: *const c_char,
|
||||||
|
guest_path: *const c_char,
|
||||||
|
) -> bool {
|
||||||
|
let guest_path = match cstr_to_path(guest_path) {
|
||||||
|
Some(p) => p,
|
||||||
|
None => return false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let dir = match cstr_to_path(path) {
|
||||||
|
Some(p) => match preopen_dir(p) {
|
||||||
|
Ok(d) => d,
|
||||||
|
Err(_) => return false,
|
||||||
|
},
|
||||||
|
None => return false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut config = Box::from_raw(config);
|
||||||
|
config.builder = config.builder.preopened_dir(dir, guest_path);
|
||||||
|
std::mem::forget(config);
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct wasi_instance_t {
|
||||||
|
wasi: Wasi,
|
||||||
|
export_cache: HashMap<String, *mut wasm_extern_t>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for wasi_instance_t {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
for v in self.export_cache.values() {
|
||||||
|
drop(unsafe { Box::from_raw(*v) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasi_instance_new(
|
||||||
|
store: *mut wasm_store_t,
|
||||||
|
config: *mut wasi_config_t,
|
||||||
|
trap: *mut *mut wasm_trap_t,
|
||||||
|
) -> *mut wasi_instance_t {
|
||||||
|
let store = &(*store).store.borrow();
|
||||||
|
let config = Box::from_raw(config);
|
||||||
|
|
||||||
|
match config.builder.build() {
|
||||||
|
Ok(ctx) => Box::into_raw(Box::new(wasi_instance_t {
|
||||||
|
wasi: Wasi::new(store, ctx),
|
||||||
|
export_cache: HashMap::new(),
|
||||||
|
})),
|
||||||
|
Err(e) => {
|
||||||
|
(*trap) = Box::into_raw(Box::new(wasm_trap_t {
|
||||||
|
trap: HostRef::new(Trap::new(e.to_string())),
|
||||||
|
}));
|
||||||
|
|
||||||
|
std::ptr::null_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasi_instance_delete(instance: *mut wasi_instance_t) {
|
||||||
|
drop(Box::from_raw(instance));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasi_instance_bind_import(
|
||||||
|
instance: *mut wasi_instance_t,
|
||||||
|
import: *const wasm_importtype_t,
|
||||||
|
) -> *const wasm_extern_t {
|
||||||
|
// TODO: support previous versions?
|
||||||
|
if (*import).ty.module() != "wasi_snapshot_preview1" {
|
||||||
|
return std::ptr::null_mut();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The import should be a function (WASI only exports functions)
|
||||||
|
let func_type = match (*import).ty.ty() {
|
||||||
|
ExternType::Func(f) => f,
|
||||||
|
_ => return std::ptr::null_mut(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let name = (*import).ty.name();
|
||||||
|
|
||||||
|
match (*instance).wasi.get_export(name) {
|
||||||
|
Some(export) => {
|
||||||
|
if export.ty().params() != func_type.params() {
|
||||||
|
return std::ptr::null_mut();
|
||||||
|
}
|
||||||
|
|
||||||
|
if export.ty().results() != func_type.results() {
|
||||||
|
return std::ptr::null_mut();
|
||||||
|
}
|
||||||
|
|
||||||
|
*(*instance)
|
||||||
|
.export_cache
|
||||||
|
.entry(name.to_string())
|
||||||
|
.or_insert_with(|| {
|
||||||
|
Box::into_raw(Box::new(wasm_extern_t {
|
||||||
|
which: ExternHost::Func(HostRef::new(export.clone())),
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
None => std::ptr::null_mut(),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -142,16 +142,15 @@ namespace Tutorial
|
|||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
using (var engine = new Engine())
|
using var engine = new Engine();
|
||||||
using (var store = engine.CreateStore())
|
using var store = engine.CreateStore();
|
||||||
using (var module = store.CreateModule("hello.wasm"))
|
using var module = store.CreateModule("hello.wasm");
|
||||||
using (dynamic instance = module.Instantiate(new Host()))
|
using dynamic instance = module.Instantiate(new Host());
|
||||||
{
|
|
||||||
instance.run();
|
instance.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The `Host` class is responsible for implementing the imported [functions](https://webassembly.github.io/spec/core/syntax/modules.html#functions), [globals](https://webassembly.github.io/spec/core/syntax/modules.html#globals), [memories](https://webassembly.github.io/spec/core/syntax/modules.html#memories), and [tables](https://webassembly.github.io/spec/core/syntax/modules.html#syntax-table) for the WebAssembly module. For Wasmtime for .NET, this is done via the [`Import`](https://peterhuene.github.io/wasmtime.net/api/Wasmtime.ImportAttribute.html) attribute applied to functions and fields of type [`Global<T>`](https://peterhuene.github.io/wasmtime.net/api/Wasmtime.Global-1.html), [`MutableGlobal<T>`](https://peterhuene.github.io/wasmtime.net/api/Wasmtime.MutableGlobal-1.html), and [`Memory`](https://peterhuene.github.io/wasmtime.net/api/Wasmtime.Memory.html) (support for WebAssembly tables is not yet implemented). The [`Instance`](https://peterhuene.github.io/wasmtime.net/api/Wasmtime.IHost.html#Wasmtime_IHost_Instance) property of the host is set during instantiation of the WebAssembly module.
|
The `Host` class is responsible for implementing the imported [functions](https://webassembly.github.io/spec/core/syntax/modules.html#functions), [globals](https://webassembly.github.io/spec/core/syntax/modules.html#globals), [memories](https://webassembly.github.io/spec/core/syntax/modules.html#memories), and [tables](https://webassembly.github.io/spec/core/syntax/modules.html#syntax-table) for the WebAssembly module. For Wasmtime for .NET, this is done via the [`Import`](https://peterhuene.github.io/wasmtime.net/api/Wasmtime.ImportAttribute.html) attribute applied to functions and fields of type [`Global<T>`](https://peterhuene.github.io/wasmtime.net/api/Wasmtime.Global-1.html), [`MutableGlobal<T>`](https://peterhuene.github.io/wasmtime.net/api/Wasmtime.MutableGlobal-1.html), and [`Memory`](https://peterhuene.github.io/wasmtime.net/api/Wasmtime.Memory.html) (support for WebAssembly tables is not yet implemented). The [`Instance`](https://peterhuene.github.io/wasmtime.net/api/Wasmtime.IHost.html#Wasmtime_IHost_Instance) property of the host is set during instantiation of the WebAssembly module.
|
||||||
|
|||||||
@@ -21,13 +21,12 @@ namespace HelloExample
|
|||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
using (var engine = new Engine())
|
using var engine = new Engine();
|
||||||
using (var store = engine.CreateStore())
|
using var store = engine.CreateStore();
|
||||||
using (var module = store.CreateModule("global.wasm"))
|
using var module = store.CreateModule("global.wasm");
|
||||||
using (dynamic instance = module.Instantiate(new Host()))
|
using dynamic instance = module.Instantiate(new Host());
|
||||||
{
|
|
||||||
instance.run(20);
|
instance.run(20);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -18,13 +18,12 @@ namespace HelloExample
|
|||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
using (var engine = new Engine())
|
using var engine = new Engine();
|
||||||
using (var store = engine.CreateStore())
|
using var store = engine.CreateStore();
|
||||||
using (var module = store.CreateModule("hello.wasm"))
|
using var module = store.CreateModule("hello.wasm");
|
||||||
using (dynamic instance = module.Instantiate(new Host()))
|
using dynamic instance = module.Instantiate(new Host());
|
||||||
{
|
|
||||||
instance.run();
|
instance.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -19,13 +19,12 @@ namespace HelloExample
|
|||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
using (var engine = new Engine())
|
using var engine = new Engine();
|
||||||
using (var store = engine.CreateStore())
|
using var store = engine.CreateStore();
|
||||||
using (var module = store.CreateModule("memory.wasm"))
|
using var module = store.CreateModule("memory.wasm");
|
||||||
using (dynamic instance = module.Instantiate(new Host()))
|
using dynamic instance = module.Instantiate(new Host());
|
||||||
{
|
|
||||||
instance.run();
|
instance.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -10,35 +10,37 @@ namespace Wasmtime.Bindings
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an abstract host binding.
|
/// Represents an abstract host binding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class Binding
|
internal abstract class Binding
|
||||||
{
|
{
|
||||||
internal abstract SafeHandle Bind(Store store, IHost host);
|
public abstract SafeHandle Bind(Store store, IHost host);
|
||||||
|
|
||||||
internal static void ThrowBindingException(Import import, MemberInfo member, string message)
|
public static WasmtimeException CreateBindingException(Import import, MemberInfo member, string message)
|
||||||
{
|
{
|
||||||
throw new WasmtimeException($"Unable to bind '{member.DeclaringType.Name}.{member.Name}' to WebAssembly import '{import}': {message}.");
|
return new WasmtimeException($"Unable to bind '{member.DeclaringType.Name}.{member.Name}' to WebAssembly import '{import}': {message}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static List<Binding> GetImportBindings(IHost host, Module module)
|
public static List<Binding> GetImportBindings(Module module, Wasi wasi = null, IHost host = null)
|
||||||
{
|
{
|
||||||
if (host is null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(host));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (module is null)
|
if (module is null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(module));
|
throw new ArgumentNullException(nameof(module));
|
||||||
}
|
}
|
||||||
|
|
||||||
var flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly;
|
|
||||||
var type = host.GetType();
|
|
||||||
var methods = type.GetMethods(flags).Where(m => !m.IsSpecialName && Attribute.IsDefined(m, typeof(ImportAttribute)));
|
|
||||||
var fields = type.GetFields(flags).Where(m => !m.IsSpecialName && Attribute.IsDefined(m, typeof(ImportAttribute)));
|
|
||||||
|
|
||||||
var bindings = new List<Binding>();
|
var bindings = new List<Binding>();
|
||||||
|
var flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly;
|
||||||
|
var type = host?.GetType();
|
||||||
|
var methods = type?.GetMethods(flags).Where(m => !m.IsSpecialName && Attribute.IsDefined(m, typeof(ImportAttribute)));
|
||||||
|
var fields = type?.GetFields(flags).Where(m => !m.IsSpecialName && Attribute.IsDefined(m, typeof(ImportAttribute)));
|
||||||
|
|
||||||
foreach (var import in module.Imports.All)
|
foreach (var import in module.Imports.All)
|
||||||
{
|
{
|
||||||
|
var wasiBinding = wasi?.Bind(import);
|
||||||
|
if (!(wasiBinding is null))
|
||||||
|
{
|
||||||
|
bindings.Add(wasiBinding);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
switch (import)
|
switch (import)
|
||||||
{
|
{
|
||||||
case FunctionImport func:
|
case FunctionImport func:
|
||||||
@@ -63,7 +65,7 @@ namespace Wasmtime.Bindings
|
|||||||
|
|
||||||
private static FunctionBinding BindFunction(FunctionImport import, IEnumerable<MethodInfo> methods)
|
private static FunctionBinding BindFunction(FunctionImport import, IEnumerable<MethodInfo> methods)
|
||||||
{
|
{
|
||||||
var method = methods.Where(m =>
|
var method = methods?.Where(m =>
|
||||||
{
|
{
|
||||||
var attribute = (ImportAttribute)m.GetCustomAttribute(typeof(ImportAttribute));
|
var attribute = (ImportAttribute)m.GetCustomAttribute(typeof(ImportAttribute));
|
||||||
if (attribute is null)
|
if (attribute is null)
|
||||||
@@ -88,7 +90,7 @@ namespace Wasmtime.Bindings
|
|||||||
|
|
||||||
private static GlobalBinding BindGlobal(GlobalImport import, IEnumerable<FieldInfo> fields)
|
private static GlobalBinding BindGlobal(GlobalImport import, IEnumerable<FieldInfo> fields)
|
||||||
{
|
{
|
||||||
var field = fields.Where(f =>
|
var field = fields?.Where(f =>
|
||||||
{
|
{
|
||||||
var attribute = (ImportAttribute)f.GetCustomAttribute(typeof(ImportAttribute));
|
var attribute = (ImportAttribute)f.GetCustomAttribute(typeof(ImportAttribute));
|
||||||
return attribute.Name == import.Name &&
|
return attribute.Name == import.Name &&
|
||||||
@@ -108,7 +110,7 @@ namespace Wasmtime.Bindings
|
|||||||
|
|
||||||
private static MemoryBinding BindMemory(MemoryImport import, IEnumerable<FieldInfo> fields)
|
private static MemoryBinding BindMemory(MemoryImport import, IEnumerable<FieldInfo> fields)
|
||||||
{
|
{
|
||||||
var field = fields.Where(f =>
|
var field = fields?.Where(f =>
|
||||||
{
|
{
|
||||||
var attribute = (ImportAttribute)f.GetCustomAttribute(typeof(ImportAttribute));
|
var attribute = (ImportAttribute)f.GetCustomAttribute(typeof(ImportAttribute));
|
||||||
return attribute.Name == import.Name &&
|
return attribute.Name == import.Name &&
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace Wasmtime.Bindings
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a host function binding.
|
/// Represents a host function binding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class FunctionBinding : Binding
|
internal class FunctionBinding : Binding
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new function binding.
|
/// Constructs a new function binding.
|
||||||
@@ -46,22 +46,19 @@ namespace Wasmtime.Bindings
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public MethodInfo Method { get; private set; }
|
public MethodInfo Method { get; private set; }
|
||||||
|
|
||||||
internal override SafeHandle Bind(Store store, IHost host)
|
public override SafeHandle Bind(Store store, IHost host)
|
||||||
{
|
{
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
if (_callback != null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Cannot bind more than once.");
|
|
||||||
}
|
|
||||||
|
|
||||||
_callback = CreateCallback(store, host);
|
|
||||||
|
|
||||||
var parameters = Interop.ToValueTypeVec(Import.Parameters);
|
var parameters = Interop.ToValueTypeVec(Import.Parameters);
|
||||||
var results = Interop.ToValueTypeVec(Import.Results);
|
var results = Interop.ToValueTypeVec(Import.Results);
|
||||||
using (var funcType = Interop.wasm_functype_new(ref parameters, ref results))
|
using (var funcType = Interop.wasm_functype_new(ref parameters, ref results))
|
||||||
{
|
{
|
||||||
return Interop.wasm_func_new(store.Handle, funcType, _callback);
|
var callback = CreateCallback(store, host);
|
||||||
|
var func = Interop.wasm_func_new(store.Handle, funcType, callback);
|
||||||
|
// Store the callback with the safe handle to keep the delegate GC reachable
|
||||||
|
func.Callback = callback;
|
||||||
|
return func;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,17 +67,17 @@ namespace Wasmtime.Bindings
|
|||||||
{
|
{
|
||||||
if (Method.IsStatic)
|
if (Method.IsStatic)
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Method, "method cannot be static");
|
throw CreateBindingException(Import, Method, "method cannot be static");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Method.IsGenericMethod)
|
if (Method.IsGenericMethod)
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Method, "method cannot be generic");
|
throw CreateBindingException(Import, Method, "method cannot be generic");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Method.IsConstructor)
|
if (Method.IsConstructor)
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Method, "method cannot be a constructor");
|
throw CreateBindingException(Import, Method, "method cannot be a constructor");
|
||||||
}
|
}
|
||||||
|
|
||||||
ValidateParameters();
|
ValidateParameters();
|
||||||
@@ -93,7 +90,7 @@ namespace Wasmtime.Bindings
|
|||||||
var parameters = Method.GetParameters();
|
var parameters = Method.GetParameters();
|
||||||
if (parameters.Length != Import.Parameters.Count)
|
if (parameters.Length != Import.Parameters.Count)
|
||||||
{
|
{
|
||||||
ThrowBindingException(
|
throw CreateBindingException(
|
||||||
Import,
|
Import,
|
||||||
Method,
|
Method,
|
||||||
$"parameter mismatch: import requires {Import.Parameters.Count} but the method has {parameters.Length}");
|
$"parameter mismatch: import requires {Import.Parameters.Count} but the method has {parameters.Length}");
|
||||||
@@ -106,18 +103,18 @@ namespace Wasmtime.Bindings
|
|||||||
{
|
{
|
||||||
if (parameter.IsOut)
|
if (parameter.IsOut)
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Method, $"parameter '{parameter.Name}' cannot be an 'out' parameter");
|
throw CreateBindingException(Import, Method, $"parameter '{parameter.Name}' cannot be an 'out' parameter");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Method, $"parameter '{parameter.Name}' cannot be a 'ref' parameter");
|
throw CreateBindingException(Import, Method, $"parameter '{parameter.Name}' cannot be a 'ref' parameter");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var expected = Import.Parameters[i];
|
var expected = Import.Parameters[i];
|
||||||
if (!Interop.TryGetValueKind(parameter.ParameterType, out var kind) || !Interop.IsMatchingKind(kind, expected))
|
if (!Interop.TryGetValueKind(parameter.ParameterType, out var kind) || !Interop.IsMatchingKind(kind, expected))
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Method, $"method parameter '{parameter.Name}' is expected to be of type '{Interop.ToString(expected)}'");
|
throw CreateBindingException(Import, Method, $"method parameter '{parameter.Name}' is expected to be of type '{Interop.ToString(expected)}'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,7 +126,7 @@ namespace Wasmtime.Bindings
|
|||||||
{
|
{
|
||||||
if (Method.ReturnType != typeof(void))
|
if (Method.ReturnType != typeof(void))
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Method, "method must return void");
|
throw CreateBindingException(Import, Method, "method must return void");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (resultsCount == 1)
|
else if (resultsCount == 1)
|
||||||
@@ -137,14 +134,14 @@ namespace Wasmtime.Bindings
|
|||||||
var expected = Import.Results[0];
|
var expected = Import.Results[0];
|
||||||
if (!Interop.TryGetValueKind(Method.ReturnType, out var kind) || !Interop.IsMatchingKind(kind, expected))
|
if (!Interop.TryGetValueKind(Method.ReturnType, out var kind) || !Interop.IsMatchingKind(kind, expected))
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Method, $"return type is expected to be '{Interop.ToString(expected)}'");
|
throw CreateBindingException(Import, Method, $"return type is expected to be '{Interop.ToString(expected)}'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!IsTupleOfSize(Method.ReturnType, resultsCount))
|
if (!IsTupleOfSize(Method.ReturnType, resultsCount))
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Method, $"return type is expected to be a tuple of size {resultsCount}");
|
throw CreateBindingException(Import, Method, $"return type is expected to be a tuple of size {resultsCount}");
|
||||||
}
|
}
|
||||||
|
|
||||||
var typeArguments =
|
var typeArguments =
|
||||||
@@ -163,7 +160,7 @@ namespace Wasmtime.Bindings
|
|||||||
var expected = Import.Results[i];
|
var expected = Import.Results[i];
|
||||||
if (!Interop.TryGetValueKind(typeArgument, out var kind) || !Interop.IsMatchingKind(kind, expected))
|
if (!Interop.TryGetValueKind(typeArgument, out var kind) || !Interop.IsMatchingKind(kind, expected))
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Method, $"return tuple item #{i} is expected to be of type '{Interop.ToString(expected)}'");
|
throw CreateBindingException(Import, Method, $"return tuple item #{i} is expected to be of type '{Interop.ToString(expected)}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
@@ -340,7 +337,5 @@ namespace Wasmtime.Bindings
|
|||||||
throw new NotSupportedException("Unsupported return value type.");
|
throw new NotSupportedException("Unsupported return value type.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Interop.WasmFuncCallback _callback;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Wasmtime.Bindings
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a host global binding.
|
/// Represents a host global binding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GlobalBinding : Binding
|
internal class GlobalBinding : Binding
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new global binding.
|
/// Constructs a new global binding.
|
||||||
@@ -43,12 +43,12 @@ namespace Wasmtime.Bindings
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public FieldInfo Field { get; private set; }
|
public FieldInfo Field { get; private set; }
|
||||||
|
|
||||||
internal override SafeHandle Bind(Store store, IHost host)
|
public override SafeHandle Bind(Store store, IHost host)
|
||||||
{
|
{
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
dynamic global = Field.GetValue(host);
|
dynamic global = Field.GetValue(host);
|
||||||
if (global.Handle != null)
|
if (!(global.Handle is null))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Cannot bind more than once.");
|
throw new InvalidOperationException("Cannot bind more than once.");
|
||||||
}
|
}
|
||||||
@@ -74,17 +74,17 @@ namespace Wasmtime.Bindings
|
|||||||
{
|
{
|
||||||
if (Field.IsStatic)
|
if (Field.IsStatic)
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Field, "field cannot be static");
|
throw CreateBindingException(Import, Field, "field cannot be static");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Field.IsInitOnly)
|
if (!Field.IsInitOnly)
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Field, "field must be readonly");
|
throw CreateBindingException(Import, Field, "field must be readonly");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Field.FieldType.IsGenericType)
|
if (!Field.FieldType.IsGenericType)
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Field, "field is expected to be of type 'Global<T>'");
|
throw CreateBindingException(Import, Field, "field is expected to be of type 'Global<T>'");
|
||||||
}
|
}
|
||||||
|
|
||||||
var definition = Field.FieldType.GetGenericTypeDefinition();
|
var definition = Field.FieldType.GetGenericTypeDefinition();
|
||||||
@@ -92,19 +92,19 @@ namespace Wasmtime.Bindings
|
|||||||
{
|
{
|
||||||
if (Import.IsMutable)
|
if (Import.IsMutable)
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Field, "the import is mutable (use the 'MutableGlobal' type)");
|
throw CreateBindingException(Import, Field, "the import is mutable (use the 'MutableGlobal' type)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (definition == typeof(MutableGlobal<>))
|
else if (definition == typeof(MutableGlobal<>))
|
||||||
{
|
{
|
||||||
if (!Import.IsMutable)
|
if (!Import.IsMutable)
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Field, "the import is constant (use the 'Global' type)");
|
throw CreateBindingException(Import, Field, "the import is constant (use the 'Global' type)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Field, "field is expected to be of type 'Global<T>' or 'MutableGlobal<T>'");
|
throw CreateBindingException(Import, Field, "field is expected to be of type 'Global<T>' or 'MutableGlobal<T>'");
|
||||||
}
|
}
|
||||||
|
|
||||||
var arg = Field.FieldType.GetGenericArguments()[0];
|
var arg = Field.FieldType.GetGenericArguments()[0];
|
||||||
@@ -113,12 +113,12 @@ namespace Wasmtime.Bindings
|
|||||||
{
|
{
|
||||||
if (!Interop.IsMatchingKind(kind, Import.Kind))
|
if (!Interop.IsMatchingKind(kind, Import.Kind))
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Field, $"global type argument is expected to be of type '{Interop.ToString(Import.Kind)}'");
|
throw CreateBindingException(Import, Field, $"global type argument is expected to be of type '{Interop.ToString(Import.Kind)}'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Field, $"'{arg}' is not a valid global type");
|
throw CreateBindingException(Import, Field, $"'{arg}' is not a valid global type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Wasmtime.Bindings
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a host memory binding.
|
/// Represents a host memory binding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class MemoryBinding : Binding
|
internal class MemoryBinding : Binding
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new memory binding.
|
/// Constructs a new memory binding.
|
||||||
@@ -43,10 +43,10 @@ namespace Wasmtime.Bindings
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public FieldInfo Field { get; private set; }
|
public FieldInfo Field { get; private set; }
|
||||||
|
|
||||||
internal override SafeHandle Bind(Store store, IHost host)
|
public override SafeHandle Bind(Store store, IHost host)
|
||||||
{
|
{
|
||||||
Memory memory = (Memory)Field.GetValue(host);
|
Memory memory = (Memory)Field.GetValue(host);
|
||||||
if (memory.Handle != null)
|
if (!(memory.Handle is null))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Cannot bind more than once.");
|
throw new InvalidOperationException("Cannot bind more than once.");
|
||||||
}
|
}
|
||||||
@@ -56,11 +56,11 @@ namespace Wasmtime.Bindings
|
|||||||
|
|
||||||
if (min != Import.Minimum)
|
if (min != Import.Minimum)
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Field, $"Memory does not have the expected minimum of {Import.Minimum} page(s)");
|
throw CreateBindingException(Import, Field, $"Memory does not have the expected minimum of {Import.Minimum} page(s)");
|
||||||
}
|
}
|
||||||
if (max != Import.Maximum)
|
if (max != Import.Maximum)
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Field, $"Memory does not have the expected maximum of {Import.Maximum} page(s)");
|
throw CreateBindingException(Import, Field, $"Memory does not have the expected maximum of {Import.Maximum} page(s)");
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe
|
unsafe
|
||||||
@@ -81,17 +81,17 @@ namespace Wasmtime.Bindings
|
|||||||
{
|
{
|
||||||
if (Field.IsStatic)
|
if (Field.IsStatic)
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Field, "field cannot be static");
|
throw CreateBindingException(Import, Field, "field cannot be static");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Field.IsInitOnly)
|
if (!Field.IsInitOnly)
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Field, "field must be readonly");
|
throw CreateBindingException(Import, Field, "field must be readonly");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Field.FieldType != typeof(Memory))
|
if (Field.FieldType != typeof(Memory))
|
||||||
{
|
{
|
||||||
ThrowBindingException(Import, Field, "field is expected to be of type 'Memory'");
|
throw CreateBindingException(Import, Field, "field is expected to be of type 'Memory'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
23
crates/misc/dotnet/src/Bindings/WasiBinding.cs
Normal file
23
crates/misc/dotnet/src/Bindings/WasiBinding.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Wasmtime.Bindings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a binding to a WASI export.
|
||||||
|
/// </summary>
|
||||||
|
internal class WasiBinding : Binding
|
||||||
|
{
|
||||||
|
public WasiBinding(IntPtr handle)
|
||||||
|
{
|
||||||
|
_handle = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override SafeHandle Bind(Store store, IHost host)
|
||||||
|
{
|
||||||
|
return new Interop.WasiExportHandle(_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IntPtr _handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -63,6 +63,23 @@ namespace Wasmtime.Externs
|
|||||||
return Encoding.UTF8.GetString(Span.Slice(address, length));
|
return Encoding.UTF8.GetString(Span.Slice(address, length));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a null-terminated UTF-8 string from memory.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">The zero-based address to read from.</param>
|
||||||
|
/// <returns>Returns the string read from memory.</returns>
|
||||||
|
public string ReadNullTerminatedString(int address)
|
||||||
|
{
|
||||||
|
var slice = Span.Slice(address);
|
||||||
|
var terminator = slice.IndexOf((byte)0);
|
||||||
|
if (terminator == -1)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("string is not null terminated");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Encoding.UTF8.GetString(slice.Slice(0, terminator));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Writes a UTF-8 string at the given address.
|
/// Writes a UTF-8 string at the given address.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -14,12 +14,5 @@ namespace Wasmtime
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>A host can only bind to one module instance at a time.</remarks>
|
/// <remarks>A host can only bind to one module instance at a time.</remarks>
|
||||||
Instance Instance { get; set; }
|
Instance Instance { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the import bindings of the host given a WebAssembly module.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="module">The WebAssembly module to get the import bindings for.</param>
|
|
||||||
/// <returns>Returns the list of import bindings for the host.</returns>
|
|
||||||
List<Binding> GetImportBindings(Module module) => Binding.GetImportBindings(this, module);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,12 @@ namespace Wasmtime.Imports
|
|||||||
{
|
{
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
var moduleName = Interop.wasm_importtype_module(importType);
|
Handle = importType;
|
||||||
|
|
||||||
|
var moduleName = Interop.wasm_importtype_module(Handle);
|
||||||
ModuleName = Marshal.PtrToStringUTF8((IntPtr)moduleName->data, (int)moduleName->size);
|
ModuleName = Marshal.PtrToStringUTF8((IntPtr)moduleName->data, (int)moduleName->size);
|
||||||
|
|
||||||
var name = Interop.wasm_importtype_name(importType);
|
var name = Interop.wasm_importtype_name(Handle);
|
||||||
Name = Marshal.PtrToStringUTF8((IntPtr)name->data, (int)name->size);
|
Name = Marshal.PtrToStringUTF8((IntPtr)name->data, (int)name->size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,6 +32,8 @@ namespace Wasmtime.Imports
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; private set; }
|
public string Name { get; private set; }
|
||||||
|
|
||||||
|
internal IntPtr Handle { get; private set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,15 +6,13 @@ namespace Wasmtime.Imports
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents imported functions, globals, tables, and memories to a WebAssembly module.
|
/// Represents imported functions, globals, tables, and memories to a WebAssembly module.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Imports
|
public class Imports : IDisposable
|
||||||
{
|
{
|
||||||
internal Imports(Module module)
|
internal Imports(Module module)
|
||||||
{
|
{
|
||||||
Interop.wasm_importtype_vec_t imports;
|
Interop.wasm_importtype_vec_t imports;
|
||||||
Interop.wasm_module_imports(module.Handle, out imports);
|
Interop.wasm_module_imports(module.Handle, out imports);
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var all = new List<Import>((int)imports.size);
|
var all = new List<Import>((int)imports.size);
|
||||||
var functions = new List<FunctionImport>();
|
var functions = new List<FunctionImport>();
|
||||||
var globals = new List<GlobalImport>();
|
var globals = new List<GlobalImport>();
|
||||||
@@ -66,9 +64,14 @@ namespace Wasmtime.Imports
|
|||||||
Memories = memories;
|
Memories = memories;
|
||||||
All = all;
|
All = all;
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public unsafe void Dispose()
|
||||||
{
|
{
|
||||||
Interop.wasm_importtype_vec_delete(ref imports);
|
if (!(_imports.data is null))
|
||||||
|
{
|
||||||
|
Interop.wasm_importtype_vec_delete(ref _imports);
|
||||||
|
_imports.data = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,5 +96,7 @@ namespace Wasmtime.Imports
|
|||||||
public IReadOnlyList<MemoryImport> Memories { get; private set; }
|
public IReadOnlyList<MemoryImport> Memories { get; private set; }
|
||||||
|
|
||||||
internal IReadOnlyList<Import> All { get; private set; }
|
internal IReadOnlyList<Import> All { get; private set; }
|
||||||
|
|
||||||
|
private Interop.wasm_importtype_vec_t _imports;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Linq;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Dynamic;
|
using System.Dynamic;
|
||||||
using Wasmtime.Externs;
|
using Wasmtime.Externs;
|
||||||
|
using Wasmtime.Bindings;
|
||||||
|
|
||||||
namespace Wasmtime
|
namespace Wasmtime
|
||||||
{
|
{
|
||||||
@@ -12,22 +13,23 @@ namespace Wasmtime
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Instance : DynamicObject, IDisposable
|
public class Instance : DynamicObject, IDisposable
|
||||||
{
|
{
|
||||||
internal Instance(Module module, IHost host)
|
internal Instance(Module module, Wasi wasi = null, IHost host = null)
|
||||||
{
|
{
|
||||||
Host = host;
|
Host = host;
|
||||||
Module = module;
|
Module = module;
|
||||||
|
|
||||||
// Save the bindings to root the objects.
|
// Save the bindings to root the objects.
|
||||||
//Otherwise the GC may collect the delegates from ExternFunction for example.
|
// Otherwise the GC may collect the callback delegates from FunctionHandles for example.
|
||||||
_bindings = host.GetImportBindings(module);
|
_bindings = Binding.GetImportBindings(module, wasi, host)
|
||||||
var handles = _bindings.Select(b => b.Bind(module.Store, host)).ToList();
|
.Select(b => b.Bind(module.Store, host))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
Handle = Interop.wasm_instance_new(
|
Handle = Interop.wasm_instance_new(
|
||||||
Module.Store.Handle,
|
Module.Store.Handle,
|
||||||
Module.Handle,
|
Module.Handle,
|
||||||
handles.Select(h => ToExtern(h)).ToArray(),
|
_bindings.Select(h => ToExtern(h)).ToArray(),
|
||||||
out var trap);
|
out var trap);
|
||||||
|
|
||||||
if (trap != IntPtr.Zero)
|
if (trap != IntPtr.Zero)
|
||||||
@@ -41,12 +43,6 @@ namespace Wasmtime
|
|||||||
throw new WasmtimeException($"Failed to instantiate module '{module.Name}'.");
|
throw new WasmtimeException($"Failed to instantiate module '{module.Name}'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dispose of all function handles (not needed at runtime)
|
|
||||||
foreach (var h in handles.Where(h => h is Interop.FunctionHandle))
|
|
||||||
{
|
|
||||||
h.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
Interop.wasm_instance_exports(Handle, out _externs);
|
Interop.wasm_instance_exports(Handle, out _externs);
|
||||||
|
|
||||||
Externs = new Wasmtime.Externs.Externs(Module.Exports, _externs);
|
Externs = new Wasmtime.Externs.Externs(Module.Exports, _externs);
|
||||||
@@ -71,17 +67,27 @@ namespace Wasmtime
|
|||||||
public Wasmtime.Externs.Externs Externs { get; private set; }
|
public Wasmtime.Externs.Externs Externs { get; private set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Dispose()
|
public unsafe void Dispose()
|
||||||
{
|
{
|
||||||
if (!Handle.IsInvalid)
|
if (!Handle.IsInvalid)
|
||||||
{
|
{
|
||||||
Handle.Dispose();
|
Handle.Dispose();
|
||||||
Handle.SetHandleAsInvalid();
|
Handle.SetHandleAsInvalid();
|
||||||
}
|
}
|
||||||
if (_externs.size != UIntPtr.Zero)
|
|
||||||
|
if (!(_bindings is null))
|
||||||
|
{
|
||||||
|
foreach (var binding in _bindings)
|
||||||
|
{
|
||||||
|
binding.Dispose();
|
||||||
|
}
|
||||||
|
_bindings = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(_externs.data is null))
|
||||||
{
|
{
|
||||||
Interop.wasm_extern_vec_delete(ref _externs);
|
Interop.wasm_extern_vec_delete(ref _externs);
|
||||||
_externs.size = UIntPtr.Zero;
|
_externs.data = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,15 +140,18 @@ namespace Wasmtime
|
|||||||
case Interop.MemoryHandle m:
|
case Interop.MemoryHandle m:
|
||||||
return Interop.wasm_memory_as_extern(m);
|
return Interop.wasm_memory_as_extern(m);
|
||||||
|
|
||||||
|
case Interop.WasiExportHandle w:
|
||||||
|
return w.DangerousGetHandle();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException("Unexpected handle type.");
|
throw new NotSupportedException("Unexpected handle type.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Interop.InstanceHandle Handle { get; private set; }
|
internal Interop.InstanceHandle Handle { get; private set; }
|
||||||
|
private SafeHandle[] _bindings;
|
||||||
private Interop.wasm_extern_vec_t _externs;
|
private Interop.wasm_extern_vec_t _externs;
|
||||||
private Dictionary<string, ExternFunction> _functions;
|
private Dictionary<string, ExternFunction> _functions;
|
||||||
private Dictionary<string, ExternGlobal> _globals;
|
private Dictionary<string, ExternGlobal> _globals;
|
||||||
private List<Bindings.Binding> _bindings;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Wasmtime
|
namespace Wasmtime
|
||||||
{
|
{
|
||||||
@@ -10,6 +11,8 @@ namespace Wasmtime
|
|||||||
/// <remarks>See https://github.com/WebAssembly/wasm-c-api/blob/master/include/wasm.h for the C API reference.</remarks>
|
/// <remarks>See https://github.com/WebAssembly/wasm-c-api/blob/master/include/wasm.h for the C API reference.</remarks>
|
||||||
internal static class Interop
|
internal static class Interop
|
||||||
{
|
{
|
||||||
|
const string LibraryName = "wasmtime";
|
||||||
|
|
||||||
internal class EngineHandle : SafeHandle
|
internal class EngineHandle : SafeHandle
|
||||||
{
|
{
|
||||||
public EngineHandle() : base(IntPtr.Zero, true)
|
public EngineHandle() : base(IntPtr.Zero, true)
|
||||||
@@ -61,6 +64,8 @@ namespace Wasmtime
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WasmFuncCallback Callback { get; set; } = null;
|
||||||
|
|
||||||
public override bool IsInvalid => handle == IntPtr.Zero;
|
public override bool IsInvalid => handle == IntPtr.Zero;
|
||||||
|
|
||||||
protected override bool ReleaseHandle()
|
protected override bool ReleaseHandle()
|
||||||
@@ -175,6 +180,51 @@ namespace Wasmtime
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class WasiConfigHandle : SafeHandle
|
||||||
|
{
|
||||||
|
public WasiConfigHandle() : base(IntPtr.Zero, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsInvalid => handle == IntPtr.Zero;
|
||||||
|
|
||||||
|
protected override bool ReleaseHandle()
|
||||||
|
{
|
||||||
|
Interop.wasi_config_delete(handle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class WasiInstanceHandle : SafeHandle
|
||||||
|
{
|
||||||
|
public WasiInstanceHandle() : base(IntPtr.Zero, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsInvalid => handle == IntPtr.Zero;
|
||||||
|
|
||||||
|
protected override bool ReleaseHandle()
|
||||||
|
{
|
||||||
|
Interop.wasi_instance_delete(handle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class WasiExportHandle : SafeHandle
|
||||||
|
{
|
||||||
|
public WasiExportHandle(IntPtr handle) : base(IntPtr.Zero, false /* not owned */)
|
||||||
|
{
|
||||||
|
SetHandle(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsInvalid => handle == IntPtr.Zero;
|
||||||
|
|
||||||
|
protected override bool ReleaseHandle()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
internal unsafe struct wasm_byte_vec_t
|
internal unsafe struct wasm_byte_vec_t
|
||||||
{
|
{
|
||||||
@@ -440,323 +490,419 @@ namespace Wasmtime
|
|||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static unsafe (byte*[], GCHandle[]) ToUTF8PtrArray(IList<string> strings)
|
||||||
|
{
|
||||||
|
// Unfortunately .NET cannot currently marshal string[] as UTF-8
|
||||||
|
// See: https://github.com/dotnet/runtime/issues/7315
|
||||||
|
// Therefore, we need to marshal the strings manually
|
||||||
|
var handles = new GCHandle[strings.Count];
|
||||||
|
for (int i = 0; i < strings.Count; ++i)
|
||||||
|
{
|
||||||
|
handles[i] = GCHandle.Alloc(
|
||||||
|
Encoding.UTF8.GetBytes(strings[i]),
|
||||||
|
GCHandleType.Pinned
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var ptrs = new byte*[strings.Count];
|
||||||
|
for (int i = 0; i < strings.Count; ++i)
|
||||||
|
{
|
||||||
|
ptrs[i] = (byte*)handles[i].AddrOfPinnedObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ptrs, handles);
|
||||||
|
}
|
||||||
|
|
||||||
// Engine imports
|
// Engine imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern EngineHandle wasm_engine_new();
|
public static extern EngineHandle wasm_engine_new();
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_engine_delete(IntPtr engine);
|
public static extern void wasm_engine_delete(IntPtr engine);
|
||||||
|
|
||||||
// Store imports
|
// Store imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern StoreHandle wasm_store_new(EngineHandle engine);
|
public static extern StoreHandle wasm_store_new(EngineHandle engine);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_store_delete(IntPtr engine);
|
public static extern void wasm_store_delete(IntPtr engine);
|
||||||
|
|
||||||
// Byte vec imports
|
// Byte vec imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_byte_vec_new_empty(out wasm_byte_vec_t vec);
|
public static extern void wasm_byte_vec_new_empty(out wasm_byte_vec_t vec);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_byte_vec_new_uninitialized(out wasm_byte_vec_t vec, UIntPtr length);
|
public static extern void wasm_byte_vec_new_uninitialized(out wasm_byte_vec_t vec, UIntPtr length);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_byte_vec_new(out wasm_byte_vec_t vec, UIntPtr length, byte[] data);
|
public static extern void wasm_byte_vec_new(out wasm_byte_vec_t vec, UIntPtr length, byte[] data);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_byte_vec_copy(out wasm_byte_vec_t vec, ref wasm_byte_vec_t src);
|
public static extern void wasm_byte_vec_copy(out wasm_byte_vec_t vec, ref wasm_byte_vec_t src);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_byte_vec_delete(ref wasm_byte_vec_t vec);
|
public static extern void wasm_byte_vec_delete(ref wasm_byte_vec_t vec);
|
||||||
|
|
||||||
// Value type vec imports
|
// Value type vec imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_valtype_vec_new_empty(out wasm_valtype_vec_t vec);
|
public static extern void wasm_valtype_vec_new_empty(out wasm_valtype_vec_t vec);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_valtype_vec_new_uninitialized(out wasm_valtype_vec_t vec, UIntPtr length);
|
public static extern void wasm_valtype_vec_new_uninitialized(out wasm_valtype_vec_t vec, UIntPtr length);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_valtype_vec_new(out wasm_valtype_vec_t vec, UIntPtr length, IntPtr[] data);
|
public static extern void wasm_valtype_vec_new(out wasm_valtype_vec_t vec, UIntPtr length, IntPtr[] data);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_valtype_vec_copy(out wasm_valtype_vec_t vec, ref wasm_valtype_vec_t src);
|
public static extern void wasm_valtype_vec_copy(out wasm_valtype_vec_t vec, ref wasm_valtype_vec_t src);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_valtype_vec_delete(ref wasm_valtype_vec_t vec);
|
public static extern void wasm_valtype_vec_delete(ref wasm_valtype_vec_t vec);
|
||||||
|
|
||||||
// Extern vec imports
|
// Extern vec imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_extern_vec_new_empty(out wasm_extern_vec_t vec);
|
public static extern void wasm_extern_vec_new_empty(out wasm_extern_vec_t vec);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_extern_vec_new_uninitialized(out wasm_extern_vec_t vec, UIntPtr length);
|
public static extern void wasm_extern_vec_new_uninitialized(out wasm_extern_vec_t vec, UIntPtr length);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_extern_vec_new(out wasm_extern_vec_t vec, UIntPtr length, IntPtr[] data);
|
public static extern void wasm_extern_vec_new(out wasm_extern_vec_t vec, UIntPtr length, IntPtr[] data);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_extern_vec_copy(out wasm_extern_vec_t vec, ref wasm_extern_vec_t src);
|
public static extern void wasm_extern_vec_copy(out wasm_extern_vec_t vec, ref wasm_extern_vec_t src);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_extern_vec_delete(ref wasm_extern_vec_t vec);
|
public static extern void wasm_extern_vec_delete(ref wasm_extern_vec_t vec);
|
||||||
|
|
||||||
// Import type vec imports
|
// Import type vec imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_importtype_vec_new_empty(out wasm_importtype_vec_t vec);
|
public static extern void wasm_importtype_vec_new_empty(out wasm_importtype_vec_t vec);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_importtype_vec_new_uninitialized(out wasm_importtype_vec_t vec, UIntPtr length);
|
public static extern void wasm_importtype_vec_new_uninitialized(out wasm_importtype_vec_t vec, UIntPtr length);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_importtype_vec_new(out wasm_importtype_vec_t vec, UIntPtr length, IntPtr[] data);
|
public static extern void wasm_importtype_vec_new(out wasm_importtype_vec_t vec, UIntPtr length, IntPtr[] data);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_importtype_vec_copy(out wasm_importtype_vec_t vec, ref wasm_importtype_vec_t src);
|
public static extern void wasm_importtype_vec_copy(out wasm_importtype_vec_t vec, ref wasm_importtype_vec_t src);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_importtype_vec_delete(ref wasm_importtype_vec_t vec);
|
public static extern void wasm_importtype_vec_delete(ref wasm_importtype_vec_t vec);
|
||||||
|
|
||||||
// Export type vec imports
|
// Export type vec imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_exporttype_vec_new_empty(out wasm_exporttype_vec_t vec);
|
public static extern void wasm_exporttype_vec_new_empty(out wasm_exporttype_vec_t vec);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_exporttype_vec_new_uninitialized(out wasm_exporttype_vec_t vec, UIntPtr length);
|
public static extern void wasm_exporttype_vec_new_uninitialized(out wasm_exporttype_vec_t vec, UIntPtr length);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_exporttype_vec_new(out wasm_exporttype_vec_t vec, UIntPtr length, IntPtr[] data);
|
public static extern void wasm_exporttype_vec_new(out wasm_exporttype_vec_t vec, UIntPtr length, IntPtr[] data);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_exporttype_vec_copy(out wasm_exporttype_vec_t vec, ref wasm_exporttype_vec_t src);
|
public static extern void wasm_exporttype_vec_copy(out wasm_exporttype_vec_t vec, ref wasm_exporttype_vec_t src);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_exporttype_vec_delete(ref wasm_exporttype_vec_t vec);
|
public static extern void wasm_exporttype_vec_delete(ref wasm_exporttype_vec_t vec);
|
||||||
|
|
||||||
// Import type imports
|
// Import type imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern unsafe wasm_byte_vec_t* wasm_importtype_module(IntPtr importType);
|
public static extern unsafe wasm_byte_vec_t* wasm_importtype_module(IntPtr importType);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern unsafe wasm_byte_vec_t* wasm_importtype_name(IntPtr importType);
|
public static extern unsafe wasm_byte_vec_t* wasm_importtype_name(IntPtr importType);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern unsafe IntPtr wasm_importtype_type(IntPtr importType);
|
public static extern unsafe IntPtr wasm_importtype_type(IntPtr importType);
|
||||||
|
|
||||||
// Export type imports
|
// Export type imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern unsafe wasm_byte_vec_t* wasm_exporttype_name(IntPtr exportType);
|
public static extern unsafe wasm_byte_vec_t* wasm_exporttype_name(IntPtr exportType);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern unsafe IntPtr wasm_exporttype_type(IntPtr exportType);
|
public static extern unsafe IntPtr wasm_exporttype_type(IntPtr exportType);
|
||||||
|
|
||||||
// Module imports
|
// Module imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern ModuleHandle wasm_module_new(StoreHandle store, ref wasm_byte_vec_t bytes);
|
public static extern ModuleHandle wasm_module_new(StoreHandle store, ref wasm_byte_vec_t bytes);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_module_imports(ModuleHandle module, out wasm_importtype_vec_t imports);
|
public static extern void wasm_module_imports(ModuleHandle module, out wasm_importtype_vec_t imports);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_module_exports(ModuleHandle module, out wasm_exporttype_vec_t exports);
|
public static extern void wasm_module_exports(ModuleHandle module, out wasm_exporttype_vec_t exports);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_module_delete(IntPtr module);
|
public static extern void wasm_module_delete(IntPtr module);
|
||||||
|
|
||||||
// Value type imports
|
// Value type imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern ValueTypeHandle wasm_valtype_new(wasm_valkind_t kind);
|
public static extern ValueTypeHandle wasm_valtype_new(wasm_valkind_t kind);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_valtype_delete(IntPtr valueType);
|
public static extern void wasm_valtype_delete(IntPtr valueType);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern ValueKind wasm_valtype_kind(IntPtr valueType);
|
public static extern ValueKind wasm_valtype_kind(IntPtr valueType);
|
||||||
|
|
||||||
// Extern imports
|
// Extern imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern wasm_externkind_t wasm_extern_kind(IntPtr ext);
|
public static extern wasm_externkind_t wasm_extern_kind(IntPtr ext);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_extern_type(IntPtr ext);
|
public static extern IntPtr wasm_extern_type(IntPtr ext);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_extern_as_func(IntPtr ext);
|
public static extern IntPtr wasm_extern_as_func(IntPtr ext);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_extern_as_global(IntPtr ext);
|
public static extern IntPtr wasm_extern_as_global(IntPtr ext);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_extern_as_table(IntPtr ext);
|
public static extern IntPtr wasm_extern_as_table(IntPtr ext);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_extern_as_memory(IntPtr ext);
|
public static extern IntPtr wasm_extern_as_memory(IntPtr ext);
|
||||||
|
|
||||||
// Extern type imports
|
// Extern type imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern wasm_externkind_t wasm_externtype_kind(IntPtr externType);
|
public static extern wasm_externkind_t wasm_externtype_kind(IntPtr externType);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_externtype_as_functype_const(IntPtr externType);
|
public static extern IntPtr wasm_externtype_as_functype_const(IntPtr externType);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_externtype_as_globaltype_const(IntPtr externType);
|
public static extern IntPtr wasm_externtype_as_globaltype_const(IntPtr externType);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_externtype_as_tabletype_const(IntPtr externType);
|
public static extern IntPtr wasm_externtype_as_tabletype_const(IntPtr externType);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_externtype_as_memorytype_const(IntPtr externType);
|
public static extern IntPtr wasm_externtype_as_memorytype_const(IntPtr externType);
|
||||||
|
|
||||||
// Function imports
|
// Function imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern FunctionHandle wasm_func_new(StoreHandle store, FuncTypeHandle type, WasmFuncCallback callback);
|
public static extern FunctionHandle wasm_func_new(StoreHandle store, FuncTypeHandle type, WasmFuncCallback callback);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_func_delete(IntPtr function);
|
public static extern void wasm_func_delete(IntPtr function);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static unsafe extern IntPtr wasm_func_call(IntPtr function, wasm_val_t* args, wasm_val_t* results);
|
public static unsafe extern IntPtr wasm_func_call(IntPtr function, wasm_val_t* args, wasm_val_t* results);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_func_as_extern(FunctionHandle function);
|
public static extern IntPtr wasm_func_as_extern(FunctionHandle function);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_global_as_extern(GlobalHandle global);
|
public static extern IntPtr wasm_global_as_extern(GlobalHandle global);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_memory_as_extern(MemoryHandle memory);
|
public static extern IntPtr wasm_memory_as_extern(MemoryHandle memory);
|
||||||
|
|
||||||
// Function type imports
|
// Function type imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern unsafe wasm_valtype_vec_t* wasm_functype_params(IntPtr funcType);
|
public static extern unsafe wasm_valtype_vec_t* wasm_functype_params(IntPtr funcType);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern unsafe wasm_valtype_vec_t* wasm_functype_results(IntPtr funcType);
|
public static extern unsafe wasm_valtype_vec_t* wasm_functype_results(IntPtr funcType);
|
||||||
|
|
||||||
// Instance imports
|
// Instance imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern unsafe InstanceHandle wasm_instance_new(StoreHandle store, ModuleHandle module, IntPtr[] imports, out IntPtr trap);
|
public static extern unsafe InstanceHandle wasm_instance_new(StoreHandle store, ModuleHandle module, IntPtr[] imports, out IntPtr trap);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_instance_delete(IntPtr ext);
|
public static extern void wasm_instance_delete(IntPtr ext);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_instance_exports(InstanceHandle instance, out wasm_extern_vec_t exports);
|
public static extern void wasm_instance_exports(InstanceHandle instance, out wasm_extern_vec_t exports);
|
||||||
|
|
||||||
// Function type imports
|
// Function type imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern FuncTypeHandle wasm_functype_new(ref wasm_valtype_vec_t parameters, ref wasm_valtype_vec_t results);
|
public static extern FuncTypeHandle wasm_functype_new(ref wasm_valtype_vec_t parameters, ref wasm_valtype_vec_t results);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_functype_delete(IntPtr functype);
|
public static extern void wasm_functype_delete(IntPtr functype);
|
||||||
|
|
||||||
// Global type imports
|
// Global type imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern GlobalTypeHandle wasm_globaltype_new(IntPtr valueType, wasm_mutability_t mutability);
|
public static extern GlobalTypeHandle wasm_globaltype_new(IntPtr valueType, wasm_mutability_t mutability);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_globaltype_delete(IntPtr globalType);
|
public static extern IntPtr wasm_globaltype_delete(IntPtr globalType);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_globaltype_content(IntPtr globalType);
|
public static extern IntPtr wasm_globaltype_content(IntPtr globalType);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern wasm_mutability_t wasm_globaltype_mutability(IntPtr globalType);
|
public static extern wasm_mutability_t wasm_globaltype_mutability(IntPtr globalType);
|
||||||
|
|
||||||
// Memory type imports
|
// Memory type imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern unsafe MemoryTypeHandle wasm_memorytype_new(wasm_limits_t* limits);
|
public static extern unsafe MemoryTypeHandle wasm_memorytype_new(wasm_limits_t* limits);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_memorytype_delete(IntPtr memoryType);
|
public static extern IntPtr wasm_memorytype_delete(IntPtr memoryType);
|
||||||
|
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern unsafe wasm_limits_t* wasm_memorytype_limits(MemoryTypeHandle memoryType);
|
public static extern unsafe wasm_limits_t* wasm_memorytype_limits(MemoryTypeHandle memoryType);
|
||||||
|
|
||||||
// Trap imports
|
// Trap imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_trap_new(StoreHandle store, ref wasm_byte_vec_t message);
|
public static extern IntPtr wasm_trap_new(StoreHandle store, ref wasm_byte_vec_t message);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_trap_delete(IntPtr trap);
|
public static extern void wasm_trap_delete(IntPtr trap);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_trap_message(IntPtr trap, out wasm_byte_vec_t message);
|
public static extern void wasm_trap_message(IntPtr trap, out wasm_byte_vec_t message);
|
||||||
|
|
||||||
// Table type imports
|
// Table type imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_tabletype_element(IntPtr tableType);
|
public static extern IntPtr wasm_tabletype_element(IntPtr tableType);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static unsafe extern wasm_limits_t* wasm_tabletype_limits(IntPtr tableType);
|
public static unsafe extern wasm_limits_t* wasm_tabletype_limits(IntPtr tableType);
|
||||||
|
|
||||||
// Memory type imports
|
// Memory type imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static unsafe extern wasm_limits_t* wasm_memorytype_limits(IntPtr memoryType);
|
public static unsafe extern wasm_limits_t* wasm_memorytype_limits(IntPtr memoryType);
|
||||||
|
|
||||||
// Global imports
|
// Global imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static unsafe extern GlobalHandle wasm_global_new(StoreHandle handle, GlobalTypeHandle globalType, wasm_val_t* initialValue);
|
public static unsafe extern GlobalHandle wasm_global_new(StoreHandle handle, GlobalTypeHandle globalType, wasm_val_t* initialValue);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_global_delete(IntPtr global);
|
public static extern void wasm_global_delete(IntPtr global);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_global_type(IntPtr global);
|
public static extern IntPtr wasm_global_type(IntPtr global);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static unsafe extern void wasm_global_get(IntPtr global, wasm_val_t* value);
|
public static unsafe extern void wasm_global_get(IntPtr global, wasm_val_t* value);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static unsafe extern void wasm_global_set(IntPtr global, wasm_val_t* value);
|
public static unsafe extern void wasm_global_set(IntPtr global, wasm_val_t* value);
|
||||||
|
|
||||||
// Memory imports
|
// Memory imports
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern MemoryHandle wasm_memory_new(StoreHandle handle, MemoryTypeHandle memoryType);
|
public static extern MemoryHandle wasm_memory_new(StoreHandle handle, MemoryTypeHandle memoryType);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern void wasm_memory_delete(IntPtr memory);
|
public static extern void wasm_memory_delete(IntPtr memory);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern IntPtr wasm_memory_type(MemoryHandle memory);
|
public static extern IntPtr wasm_memory_type(MemoryHandle memory);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static unsafe extern byte* wasm_memory_data(IntPtr memory);
|
public static unsafe extern byte* wasm_memory_data(IntPtr memory);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern UIntPtr wasm_memory_data_size(IntPtr memory);
|
public static extern UIntPtr wasm_memory_data_size(IntPtr memory);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern uint wasm_memory_size(MemoryHandle memory);
|
public static extern uint wasm_memory_size(MemoryHandle memory);
|
||||||
|
|
||||||
[DllImport("wasmtime")]
|
[DllImport(LibraryName)]
|
||||||
public static extern bool wasm_memory_grow(MemoryHandle memory, uint delta);
|
public static extern bool wasm_memory_grow(MemoryHandle memory, uint delta);
|
||||||
|
|
||||||
|
// WASI config
|
||||||
|
|
||||||
|
[DllImport(LibraryName)]
|
||||||
|
public static extern WasiConfigHandle wasi_config_new();
|
||||||
|
|
||||||
|
[DllImport(LibraryName)]
|
||||||
|
public static extern void wasi_config_delete(IntPtr config);
|
||||||
|
|
||||||
|
[DllImport(LibraryName)]
|
||||||
|
public unsafe static extern void wasi_config_set_argv(WasiConfigHandle config, int argc, byte*[] argv);
|
||||||
|
|
||||||
|
[DllImport(LibraryName)]
|
||||||
|
public static extern void wasi_config_inherit_argv(WasiConfigHandle config);
|
||||||
|
|
||||||
|
[DllImport(LibraryName)]
|
||||||
|
public static extern unsafe void wasi_config_set_env(
|
||||||
|
WasiConfigHandle config,
|
||||||
|
int envc,
|
||||||
|
byte*[] names,
|
||||||
|
byte*[] values
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport(LibraryName)]
|
||||||
|
public static extern void wasi_config_inherit_env(WasiConfigHandle config);
|
||||||
|
|
||||||
|
[DllImport(LibraryName)]
|
||||||
|
public static extern bool wasi_config_set_stdin(
|
||||||
|
WasiConfigHandle config,
|
||||||
|
[MarshalAs(UnmanagedType.LPUTF8Str)] string path
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport(LibraryName)]
|
||||||
|
public static extern void wasi_config_inherit_stdin(WasiConfigHandle config);
|
||||||
|
|
||||||
|
[DllImport(LibraryName)]
|
||||||
|
public static extern bool wasi_config_set_stdout(
|
||||||
|
WasiConfigHandle config,
|
||||||
|
[MarshalAs(UnmanagedType.LPUTF8Str)] string path
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport(LibraryName)]
|
||||||
|
public static extern void wasi_config_inherit_stdout(WasiConfigHandle config);
|
||||||
|
|
||||||
|
[DllImport(LibraryName)]
|
||||||
|
public static extern bool wasi_config_set_stderr(
|
||||||
|
WasiConfigHandle config,
|
||||||
|
[MarshalAs(UnmanagedType.LPUTF8Str)] string path
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport(LibraryName)]
|
||||||
|
public static extern void wasi_config_inherit_stderr(WasiConfigHandle config);
|
||||||
|
|
||||||
|
[DllImport(LibraryName)]
|
||||||
|
public static extern bool wasi_config_preopen_dir(
|
||||||
|
WasiConfigHandle config,
|
||||||
|
[MarshalAs(UnmanagedType.LPUTF8Str)] string path,
|
||||||
|
[MarshalAs(UnmanagedType.LPUTF8Str)] string guestPath
|
||||||
|
);
|
||||||
|
|
||||||
|
// WASI instance
|
||||||
|
[DllImport(LibraryName)]
|
||||||
|
public static extern WasiInstanceHandle wasi_instance_new(
|
||||||
|
StoreHandle store,
|
||||||
|
WasiConfigHandle config,
|
||||||
|
out IntPtr trap
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport(LibraryName)]
|
||||||
|
public static extern void wasi_instance_delete(IntPtr instance);
|
||||||
|
|
||||||
|
[DllImport(LibraryName)]
|
||||||
|
public static extern IntPtr wasi_instance_bind_import(WasiInstanceHandle instance, IntPtr importType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,20 +49,33 @@ namespace Wasmtime
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="host">The host to use for the WebAssembly module's instance.</param>
|
/// <param name="host">The host to use for the WebAssembly module's instance.</param>
|
||||||
/// <returns>Returns a new <see cref="Instance" />.</returns>
|
/// <returns>Returns a new <see cref="Instance" />.</returns>
|
||||||
public Instance Instantiate(IHost host)
|
public Instance Instantiate(IHost host = null)
|
||||||
{
|
{
|
||||||
if (host is null)
|
return Instantiate(null, host);
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(host));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (host.Instance != null)
|
/// <summary>
|
||||||
|
/// Instantiates a WebAssembly module for the given host.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wasi">The WASI instance to use for WASI imports.</param>
|
||||||
|
/// <param name="host">The host to use for the WebAssembly module's instance.</param>
|
||||||
|
/// <returns>Returns a new <see cref="Instance" />.</returns>
|
||||||
|
public Instance Instantiate(Wasi wasi, IHost host = null)
|
||||||
|
{
|
||||||
|
if (!(host?.Instance is null))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("The host has already been associated with an instantiated module.");
|
throw new InvalidOperationException("The host has already been associated with an instantiated module.");
|
||||||
}
|
}
|
||||||
|
|
||||||
host.Instance = new Instance(this, host);
|
var instance = new Instance(this, wasi, host);
|
||||||
return host.Instance;
|
|
||||||
|
if (!(host is null))
|
||||||
|
{
|
||||||
|
host.Instance = instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -94,6 +107,11 @@ namespace Wasmtime
|
|||||||
Handle.Dispose();
|
Handle.Dispose();
|
||||||
Handle.SetHandleAsInvalid();
|
Handle.SetHandleAsInvalid();
|
||||||
}
|
}
|
||||||
|
if (!(Imports is null))
|
||||||
|
{
|
||||||
|
Imports.Dispose();
|
||||||
|
Imports = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Interop.ModuleHandle Handle { get; private set; }
|
internal Interop.ModuleHandle Handle { get; private set; }
|
||||||
|
|||||||
@@ -29,9 +29,11 @@ namespace Wasmtime
|
|||||||
Interop.wasm_trap_message(trap, out var bytes);
|
Interop.wasm_trap_message(trap, out var bytes);
|
||||||
var byteSpan = new ReadOnlySpan<byte>(bytes.data, checked((int)bytes.size));
|
var byteSpan = new ReadOnlySpan<byte>(bytes.data, checked((int)bytes.size));
|
||||||
|
|
||||||
int indexOfNull = byteSpan.IndexOf((byte)0);
|
int indexOfNull = byteSpan.LastIndexOf((byte)0);
|
||||||
if (indexOfNull != -1)
|
if (indexOfNull != -1)
|
||||||
|
{
|
||||||
byteSpan = byteSpan.Slice(0, indexOfNull);
|
byteSpan = byteSpan.Slice(0, indexOfNull);
|
||||||
|
}
|
||||||
|
|
||||||
var message = Encoding.UTF8.GetString(byteSpan);
|
var message = Encoding.UTF8.GetString(byteSpan);
|
||||||
Interop.wasm_byte_vec_delete(ref bytes);
|
Interop.wasm_byte_vec_delete(ref bytes);
|
||||||
|
|||||||
44
crates/misc/dotnet/src/Wasi.cs
Normal file
44
crates/misc/dotnet/src/Wasi.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using Wasmtime.Bindings;
|
||||||
|
using Wasmtime.Imports;
|
||||||
|
|
||||||
|
namespace Wasmtime
|
||||||
|
{
|
||||||
|
public class Wasi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a default <see cref="Wasi"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
public Wasi(Store store) :
|
||||||
|
this(
|
||||||
|
(store ?? throw new ArgumentNullException(nameof(store))).Handle,
|
||||||
|
Interop.wasi_config_new()
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Wasi(Interop.StoreHandle store, Interop.WasiConfigHandle config)
|
||||||
|
{
|
||||||
|
IntPtr trap;
|
||||||
|
Handle = Interop.wasi_instance_new(store, config, out trap);
|
||||||
|
config.SetHandleAsInvalid();
|
||||||
|
|
||||||
|
if (trap != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
throw TrapException.FromOwnedTrap(trap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal WasiBinding Bind(Import import)
|
||||||
|
{
|
||||||
|
var export = Interop.wasi_instance_bind_import(Handle, import.Handle);
|
||||||
|
if (export == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new WasiBinding(export);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Interop.WasiInstanceHandle Handle { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
409
crates/misc/dotnet/src/WasiBuilder.cs
Normal file
409
crates/misc/dotnet/src/WasiBuilder.cs
Normal file
@@ -0,0 +1,409 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Wasmtime
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a build of WASI instances.
|
||||||
|
/// </summary>
|
||||||
|
public class WasiBuilder
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a new <see cref="WasiBuilder" />.
|
||||||
|
/// </summary>
|
||||||
|
public WasiBuilder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a command line argument to the builder.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="arg">The command line argument to add.</param>
|
||||||
|
/// <returns>Returns the current builder.</returns>
|
||||||
|
public WasiBuilder WithArg(string arg)
|
||||||
|
{
|
||||||
|
if (arg is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_inheritArgs)
|
||||||
|
{
|
||||||
|
_args.Clear();
|
||||||
|
_inheritArgs = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_args.Add(arg);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds multiple command line arguments to the builder.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">The command line arguments to add.</param>
|
||||||
|
/// <returns>Returns the current builder.</returns>
|
||||||
|
public WasiBuilder WithArgs(IEnumerable<string> args)
|
||||||
|
{
|
||||||
|
if (args is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_inheritArgs)
|
||||||
|
{
|
||||||
|
_args.Clear();
|
||||||
|
_inheritArgs = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var arg in args)
|
||||||
|
{
|
||||||
|
_args.Add(arg);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds multiple command line arguments to the builder.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">The command line arguments to add.</param>
|
||||||
|
/// <returns>Returns the current builder.</returns>
|
||||||
|
public WasiBuilder WithArgs(params string[] args)
|
||||||
|
{
|
||||||
|
return WithArgs((IEnumerable<string>)args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the builder to inherit command line arguments.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Any explicitly specified command line arguments will be removed.</remarks>
|
||||||
|
/// <returns>Returns the current builder.</returns>
|
||||||
|
public WasiBuilder WithInheritedArgs()
|
||||||
|
{
|
||||||
|
_inheritArgs = true;
|
||||||
|
_args.Clear();
|
||||||
|
_args.AddRange(Environment.GetCommandLineArgs());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds an environment variable to the builder.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name of the environment variable.</param>
|
||||||
|
/// <param name="value">The value of the environment variable.</param>
|
||||||
|
/// <returns>Returns the current builder.</returns>
|
||||||
|
public WasiBuilder WithEnvironmentVariable(string name, string value)
|
||||||
|
{
|
||||||
|
if (name is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(name));
|
||||||
|
}
|
||||||
|
if (value is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Environment variable name cannot be empty.", nameof(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
_inheritEnv = false;
|
||||||
|
_vars.Add((name, value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds multiple environment variables to the builder.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vars">The name-value tuples of the environment variables to add.</param>
|
||||||
|
/// <returns>Returns the current builder.</returns>
|
||||||
|
public WasiBuilder WithEnvironmentVariables(IEnumerable<(string,string)> vars)
|
||||||
|
{
|
||||||
|
if (vars is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(vars));
|
||||||
|
}
|
||||||
|
|
||||||
|
_inheritEnv = false;
|
||||||
|
|
||||||
|
foreach (var v in vars)
|
||||||
|
{
|
||||||
|
_vars.Add(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the builder to inherit environment variables.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Any explicitly specified environment variables will be removed.</remarks>
|
||||||
|
/// <returns>Returns the current builder.</returns>
|
||||||
|
public WasiBuilder WithInheritedEnvironment()
|
||||||
|
{
|
||||||
|
_inheritEnv = true;
|
||||||
|
_vars.Clear();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the builder to use the given file path as stdin.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The file to use as stdin.</param>
|
||||||
|
/// <returns>Returns the current builder.</returns>
|
||||||
|
public WasiBuilder WithStandardInput(string path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The path cannot be null or empty.", nameof(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
_inheritStandardInput = false;
|
||||||
|
_standardInputPath = path;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the builder to inherit stdin.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Any explicitly specified stdin file will be removed.</remarks>
|
||||||
|
/// <returns>Returns the current builder.</returns>
|
||||||
|
public WasiBuilder WithInheritedStandardInput()
|
||||||
|
{
|
||||||
|
_inheritStandardInput = true;
|
||||||
|
_standardInputPath = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the builder to use the given file path as stdout.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The file to use as stdout.</param>
|
||||||
|
/// <returns>Returns the current builder.</returns>
|
||||||
|
public WasiBuilder WithStandardOutput(string path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The path cannot be null or empty.", nameof(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
_inheritStandardOutput = false;
|
||||||
|
_standardOutputPath = path;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the builder to inherit stdout.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Any explicitly specified stdout file will be removed.</remarks>
|
||||||
|
/// <returns>Returns the current builder.</returns>
|
||||||
|
public WasiBuilder WithInheritedStandardOutput()
|
||||||
|
{
|
||||||
|
_inheritStandardOutput = true;
|
||||||
|
_standardOutputPath = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the builder to use the given file path as stderr.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The file to use as stderr.</param>
|
||||||
|
/// <returns>Returns the current builder.</returns>
|
||||||
|
public WasiBuilder WithStandardError(string path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The path cannot be null or empty.", nameof(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
_inheritStandardError = false;
|
||||||
|
_standardErrorPath = path;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the builder to inherit stderr.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Any explicitly specified stderr file will be removed.</remarks>
|
||||||
|
/// <returns>Returns the current builder.</returns>
|
||||||
|
public WasiBuilder WithInheritedStandardError()
|
||||||
|
{
|
||||||
|
_inheritStandardError = true;
|
||||||
|
_standardErrorPath = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a preopen directory to the builder.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path to the directory to add.</param>
|
||||||
|
/// <param name="guestPath">The path the guest will use to open the directory.</param>
|
||||||
|
/// <returns>Returns the current builder.</returns>
|
||||||
|
public WasiBuilder WithPreopenedDirectory(string path, string guestPath)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The path cannot be null or empty.", nameof(path));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(guestPath))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The guest path cannot be null or empty.", nameof(guestPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
_preopenDirs.Add((path, guestPath));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Builds the <see cref="Wasi" /> instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="store">The <see cref="Store" /> to use.</param>
|
||||||
|
/// <returns>Returns the new <see cref="Wasi" /> instance.</returns>
|
||||||
|
public Wasi Build(Store store)
|
||||||
|
{
|
||||||
|
var config = Interop.wasi_config_new();
|
||||||
|
|
||||||
|
SetConfigArgs(config);
|
||||||
|
SetEnvironmentVariables(config);
|
||||||
|
SetStandardIn(config);
|
||||||
|
SetStandardOut(config);
|
||||||
|
SetStandardError(config);
|
||||||
|
SetPreopenDirectories(config);
|
||||||
|
|
||||||
|
return new Wasi(store.Handle, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe void SetConfigArgs(Interop.WasiConfigHandle config)
|
||||||
|
{
|
||||||
|
// Don't call wasi_config_inherit_argv as the command line to the .NET program may not be
|
||||||
|
// the same as the process' command line (e.g. `dotnet foo.dll foo bar baz` => "foo.dll foo bar baz").
|
||||||
|
if (_args.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var (args, handles) = Interop.ToUTF8PtrArray(_args);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Interop.wasi_config_set_argv(config, _args.Count, args);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
foreach (var handle in handles)
|
||||||
|
{
|
||||||
|
handle.Free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe void SetEnvironmentVariables(Interop.WasiConfigHandle config)
|
||||||
|
{
|
||||||
|
if (_inheritEnv)
|
||||||
|
{
|
||||||
|
Interop.wasi_config_inherit_env(config);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_vars.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var (names, nameHandles) = Interop.ToUTF8PtrArray(_vars.Select(var => var.Name).ToArray());
|
||||||
|
var (values, valueHandles) = Interop.ToUTF8PtrArray(_vars.Select(var => var.Value).ToArray());
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Interop.wasi_config_set_env(config, _vars.Count, names, values);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
foreach (var handle in nameHandles)
|
||||||
|
{
|
||||||
|
handle.Free();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var handle in valueHandles)
|
||||||
|
{
|
||||||
|
handle.Free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetStandardIn(Interop.WasiConfigHandle config)
|
||||||
|
{
|
||||||
|
if (_inheritStandardInput)
|
||||||
|
{
|
||||||
|
Interop.wasi_config_inherit_stdin(config);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(_standardInputPath))
|
||||||
|
{
|
||||||
|
if (!Interop.wasi_config_set_stdin(config, _standardInputPath))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Failed to set stdin to file '{_standardInputPath}'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetStandardOut(Interop.WasiConfigHandle config)
|
||||||
|
{
|
||||||
|
if (_inheritStandardOutput)
|
||||||
|
{
|
||||||
|
Interop.wasi_config_inherit_stdout(config);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(_standardOutputPath))
|
||||||
|
{
|
||||||
|
if (!Interop.wasi_config_set_stdout(config, _standardOutputPath))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Failed to set stdout to file '{_standardOutputPath}'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetStandardError(Interop.WasiConfigHandle config)
|
||||||
|
{
|
||||||
|
if (_inheritStandardError)
|
||||||
|
{
|
||||||
|
Interop.wasi_config_inherit_stderr(config);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(_standardErrorPath))
|
||||||
|
{
|
||||||
|
if (!Interop.wasi_config_set_stderr(config, _standardErrorPath))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Failed to set stderr to file '{_standardErrorPath}'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetPreopenDirectories(Interop.WasiConfigHandle config)
|
||||||
|
{
|
||||||
|
foreach (var dir in _preopenDirs)
|
||||||
|
{
|
||||||
|
if (!Interop.wasi_config_preopen_dir(config, dir.Path, dir.GuestPath))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Failed to preopen directory '{dir.Path}'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly List<string> _args = new List<string>();
|
||||||
|
private readonly List<(string Name, string Value)> _vars = new List<(string, string)>();
|
||||||
|
private string _standardInputPath;
|
||||||
|
private string _standardOutputPath;
|
||||||
|
private string _standardErrorPath;
|
||||||
|
private readonly List<(string Path, string GuestPath)> _preopenDirs = new List<(string, string)>();
|
||||||
|
private bool _inheritArgs = false;
|
||||||
|
private bool _inheritEnv = false;
|
||||||
|
private bool _inheritStandardInput = false;
|
||||||
|
private bool _inheritStandardOutput = false;
|
||||||
|
private bool _inheritStandardError = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,19 +15,19 @@ namespace Wasmtime.Tests
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (Module != null)
|
if (!(Module is null))
|
||||||
{
|
{
|
||||||
Module.Dispose();
|
Module.Dispose();
|
||||||
Module = null;
|
Module = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Store != null)
|
if (!(Store is null))
|
||||||
{
|
{
|
||||||
Store.Dispose();
|
Store.Dispose();
|
||||||
Store = null;
|
Store = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Engine != null)
|
if (!(Engine is null))
|
||||||
{
|
{
|
||||||
Engine.Dispose();
|
Engine.Dispose();
|
||||||
Engine = null;
|
Engine = null;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Wasmtime.Tests
|
|||||||
|
|
||||||
public class FunctionThunkingTests : IClassFixture<FunctionThunkingFixture>
|
public class FunctionThunkingTests : IClassFixture<FunctionThunkingFixture>
|
||||||
{
|
{
|
||||||
const string THROW_MESSAGE = "Test error messages for wasmtime dotnet bidnings unit tests.";
|
const string THROW_MESSAGE = "Test error message for wasmtime dotnet unit tests.";
|
||||||
|
|
||||||
class MyHost : IHost
|
class MyHost : IHost
|
||||||
{
|
{
|
||||||
@@ -53,7 +53,7 @@ namespace Wasmtime.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ItPropegatesExceptionsToCallersViaTraps()
|
public void ItPropagatesExceptionsToCallersViaTraps()
|
||||||
{
|
{
|
||||||
var host = new MyHost();
|
var host = new MyHost();
|
||||||
using (var instance = Fixture.Module.Instantiate(host))
|
using (var instance = Fixture.Module.Instantiate(host))
|
||||||
|
|||||||
@@ -113,6 +113,27 @@ impl WasiCtxBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Inherit stdin from the host process.
|
||||||
|
pub fn inherit_stdin(mut self) -> Self {
|
||||||
|
self.fds
|
||||||
|
.insert(0, PendingFdEntry::Thunk(FdEntry::duplicate_stdin));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inherit stdout from the host process.
|
||||||
|
pub fn inherit_stdout(mut self) -> Self {
|
||||||
|
self.fds
|
||||||
|
.insert(1, PendingFdEntry::Thunk(FdEntry::duplicate_stdout));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inherit stdout from the host process.
|
||||||
|
pub fn inherit_stderr(mut self) -> Self {
|
||||||
|
self.fds
|
||||||
|
.insert(2, PendingFdEntry::Thunk(FdEntry::duplicate_stderr));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Inherit the stdin, stdout, and stderr streams from the host process.
|
/// Inherit the stdin, stdout, and stderr streams from the host process.
|
||||||
pub fn inherit_stdio(mut self) -> Self {
|
pub fn inherit_stdio(mut self) -> Self {
|
||||||
self.fds
|
self.fds
|
||||||
|
|||||||
Reference in New Issue
Block a user