mirror of
https://github.com/fluencelabs/wasmer
synced 2025-04-24 18:02:13 +00:00
Implement instance.exports
field syntax
This commit is contained in:
parent
c14c88fb72
commit
a18371eb91
@ -6,7 +6,7 @@
|
|||||||
- [#1313](https://github.com/wasmerio/wasmer/pull/1313) Add new high-level public API through `wasmer` crate. Includes many updates including:
|
- [#1313](https://github.com/wasmerio/wasmer/pull/1313) Add new high-level public API through `wasmer` crate. Includes many updates including:
|
||||||
- Minor improvement: `imports!` macro now handles no trailing comma as well as a trailing comma in namespaces and between namespaces.
|
- Minor improvement: `imports!` macro now handles no trailing comma as well as a trailing comma in namespaces and between namespaces.
|
||||||
- New methods on `Module`: `exports`, `imports`, and `custom_sections`.
|
- New methods on `Module`: `exports`, `imports`, and `custom_sections`.
|
||||||
- TODO: update this when the method name changes. New way to get exports from an instance with `let func_name: Func<i32, i64> = instance.exports_new().get("func_name");`.
|
- New way to get exports from an instance with `let func_name: Func<i32, i64> = instance.exports.get("func_name");`.
|
||||||
- Improved `Table` APIs including `set` which now allows setting functions directly. TODO: update this more if `Table::get` gets made public in this PR
|
- Improved `Table` APIs including `set` which now allows setting functions directly. TODO: update this more if `Table::get` gets made public in this PR
|
||||||
- TODO: finish the list of changes here
|
- TODO: finish the list of changes here
|
||||||
- [#1303](https://github.com/wasmerio/wasmer/pull/1303) NaN canonicalization for singlepass backend.
|
- [#1303](https://github.com/wasmerio/wasmer/pull/1303) NaN canonicalization for singlepass backend.
|
||||||
|
@ -128,19 +128,19 @@ fn it_works() {
|
|||||||
};
|
};
|
||||||
let instance = module.instantiate(&import_object).unwrap();
|
let instance = module.instantiate(&import_object).unwrap();
|
||||||
|
|
||||||
let ret_2: Func<(), i32> = instance.exports_new().get("ret_2").unwrap();
|
let ret_2: Func<(), i32> = instance.exports.get("ret_2").unwrap();
|
||||||
let ret_4: Func<(), i32> = instance.exports_new().get("ret_4").unwrap();
|
let ret_4: Func<(), i32> = instance.exports.get("ret_4").unwrap();
|
||||||
let set_test_global: Func<i32> = instance.exports_new().get("set_test_global").unwrap();
|
let set_test_global: Func<i32> = instance.exports.get("set_test_global").unwrap();
|
||||||
let update_outside_global: Func = instance.exports_new().get("update_outside_global").unwrap();
|
let update_outside_global: Func = instance.exports.get("update_outside_global").unwrap();
|
||||||
|
|
||||||
assert_eq!(ret_2.call(), Ok(2));
|
assert_eq!(ret_2.call(), Ok(2));
|
||||||
assert_eq!(ret_4.call(), Ok(4));
|
assert_eq!(ret_4.call(), Ok(4));
|
||||||
|
|
||||||
let _test_table: Table = instance.exports_new().get("test-table").unwrap();
|
let _test_table: Table = instance.exports.get("test-table").unwrap();
|
||||||
// TODO: when table get is stablized test this
|
// TODO: when table get is stablized test this
|
||||||
|
|
||||||
let test_global: Global = instance.exports_new().get("test-global").unwrap();
|
let test_global: Global = instance.exports.get("test-global").unwrap();
|
||||||
// TODO: do we want to make global.get act like exports_new().get()?
|
// TODO: do we want to make global.get act like exports.get()?
|
||||||
assert_eq!(test_global.get(), Value::I32(3));
|
assert_eq!(test_global.get(), Value::I32(3));
|
||||||
set_test_global.call(17).unwrap();
|
set_test_global.call(17).unwrap();
|
||||||
assert_eq!(test_global.get(), Value::I32(17));
|
assert_eq!(test_global.get(), Value::I32(17));
|
||||||
|
@ -30,13 +30,13 @@ fn new_api_works() {
|
|||||||
let import_object = imports! {};
|
let import_object = imports! {};
|
||||||
let instance = module.instantiate(&import_object).unwrap();
|
let instance = module.instantiate(&import_object).unwrap();
|
||||||
|
|
||||||
let my_global: Global = instance.exports_new().get("my_global").unwrap();
|
let my_global: Global = instance.exports.get("my_global").unwrap();
|
||||||
assert_eq!(my_global.get(), Value::I32(45));
|
assert_eq!(my_global.get(), Value::I32(45));
|
||||||
let double: Func<i32, i32> = instance.exports_new().get("double").unwrap();
|
let double: Func<i32, i32> = instance.exports.get("double").unwrap();
|
||||||
assert_eq!(double.call(5).unwrap(), 10);
|
assert_eq!(double.call(5).unwrap(), 10);
|
||||||
let add_one: DynFunc = instance.exports_new().get("add_one").unwrap();
|
let add_one: DynFunc = instance.exports.get("add_one").unwrap();
|
||||||
assert_eq!(add_one.call(&[Value::I32(5)]).unwrap(), &[Value::I32(6)]);
|
assert_eq!(add_one.call(&[Value::I32(5)]).unwrap(), &[Value::I32(6)]);
|
||||||
let add_one_memory: Option<DynFunc> = instance.exports_new().get("my_global");
|
let add_one_memory: Option<DynFunc> = instance.exports.get("my_global");
|
||||||
assert!(add_one_memory.is_none());
|
assert!(add_one_memory.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
//! including memories, tables, globals, and functions.
|
//! including memories, tables, globals, and functions.
|
||||||
use crate::{
|
use crate::{
|
||||||
global::Global,
|
global::Global,
|
||||||
instance::{Instance, InstanceInner},
|
instance::{Exports, InstanceInner},
|
||||||
memory::Memory,
|
memory::Memory,
|
||||||
module::ExportIndex,
|
module::ExportIndex,
|
||||||
module::ModuleInner,
|
module::ModuleInner,
|
||||||
@ -102,5 +102,5 @@ impl<'a> Iterator for ExportIter<'a> {
|
|||||||
pub trait Exportable<'a>: Sized {
|
pub trait Exportable<'a>: Sized {
|
||||||
/// Implementation of how to get the export corresponding to the implementing type
|
/// Implementation of how to get the export corresponding to the implementing type
|
||||||
/// from an [`Instance`] by name.
|
/// from an [`Instance`] by name.
|
||||||
fn get_self(instance: &'a Instance, name: &str) -> Option<Self>;
|
fn get_self(exports: &'a Exports, name: &str) -> Option<Self>;
|
||||||
}
|
}
|
||||||
|
@ -56,16 +56,13 @@ pub struct Instance {
|
|||||||
/// Reference to the module used to instantiate this instance.
|
/// Reference to the module used to instantiate this instance.
|
||||||
pub module: Arc<ModuleInner>,
|
pub module: Arc<ModuleInner>,
|
||||||
inner: Pin<Box<InstanceInner>>,
|
inner: Pin<Box<InstanceInner>>,
|
||||||
|
/// The exports of this instance. TODO: document this
|
||||||
|
pub exports: Exports,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
import_object: ImportObject,
|
import_object: ImportObject,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
/// Access the new exports API.
|
|
||||||
/// TODO: rename etc.
|
|
||||||
pub fn exports_new(&self) -> Exports {
|
|
||||||
Exports { instance: self }
|
|
||||||
}
|
|
||||||
pub(crate) fn new(module: Arc<ModuleInner>, imports: &ImportObject) -> Result<Instance> {
|
pub(crate) fn new(module: Arc<ModuleInner>, imports: &ImportObject) -> Result<Instance> {
|
||||||
// We need the backing and import_backing to create a vm::Ctx, but we need
|
// We need the backing and import_backing to create a vm::Ctx, but we need
|
||||||
// a vm::Ctx to create a backing and an import_backing. The solution is to create an
|
// a vm::Ctx to create a backing and an import_backing. The solution is to create an
|
||||||
@ -97,9 +94,15 @@ impl Instance {
|
|||||||
};
|
};
|
||||||
Box::leak(vmctx);
|
Box::leak(vmctx);
|
||||||
|
|
||||||
|
let exports = Exports {
|
||||||
|
module: module.clone(),
|
||||||
|
instance_inner: &*inner as *const InstanceInner,
|
||||||
|
};
|
||||||
|
|
||||||
let instance = Instance {
|
let instance = Instance {
|
||||||
module,
|
module,
|
||||||
inner,
|
inner,
|
||||||
|
exports,
|
||||||
import_object: imports.clone_ref(),
|
import_object: imports.clone_ref(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -183,77 +186,7 @@ impl Instance {
|
|||||||
Args: WasmTypeList,
|
Args: WasmTypeList,
|
||||||
Rets: WasmTypeList,
|
Rets: WasmTypeList,
|
||||||
{
|
{
|
||||||
let export_index =
|
func(&*self.module, &self.inner, name)
|
||||||
self.module
|
|
||||||
.info
|
|
||||||
.exports
|
|
||||||
.get(name)
|
|
||||||
.ok_or_else(|| ResolveError::ExportNotFound {
|
|
||||||
name: name.to_string(),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if let ExportIndex::Func(func_index) = export_index {
|
|
||||||
let sig_index = *self
|
|
||||||
.module
|
|
||||||
.info
|
|
||||||
.func_assoc
|
|
||||||
.get(*func_index)
|
|
||||||
.expect("broken invariant, incorrect func index");
|
|
||||||
let signature =
|
|
||||||
SigRegistry.lookup_signature_ref(&self.module.info.signatures[sig_index]);
|
|
||||||
|
|
||||||
if signature.params() != Args::types() || signature.returns() != Rets::types() {
|
|
||||||
Err(ResolveError::Signature {
|
|
||||||
expected: (*signature).clone(),
|
|
||||||
found: Args::types().to_vec(),
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ctx = match func_index.local_or_import(&self.module.info) {
|
|
||||||
LocalOrImport::Local(_) => self.inner.vmctx,
|
|
||||||
LocalOrImport::Import(imported_func_index) => unsafe {
|
|
||||||
self.inner.import_backing.vm_functions[imported_func_index]
|
|
||||||
.func_ctx
|
|
||||||
.as_ref()
|
|
||||||
}
|
|
||||||
.vmctx
|
|
||||||
.as_ptr(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let func_wasm_inner = self
|
|
||||||
.module
|
|
||||||
.runnable_module
|
|
||||||
.get_trampoline(&self.module.info, sig_index)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let (func_ptr, func_env) = match func_index.local_or_import(&self.module.info) {
|
|
||||||
LocalOrImport::Local(local_func_index) => (
|
|
||||||
self.module
|
|
||||||
.runnable_module
|
|
||||||
.get_func(&self.module.info, local_func_index)
|
|
||||||
.unwrap(),
|
|
||||||
None,
|
|
||||||
),
|
|
||||||
LocalOrImport::Import(import_func_index) => {
|
|
||||||
let imported_func = &self.inner.import_backing.vm_functions[import_func_index];
|
|
||||||
|
|
||||||
(
|
|
||||||
NonNull::new(imported_func.func as *mut _).unwrap(),
|
|
||||||
unsafe { imported_func.func_ctx.as_ref() }.func_env,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let typed_func: Func<Args, Rets, Wasm> =
|
|
||||||
unsafe { Func::from_raw_parts(func_wasm_inner, func_ptr, func_env, ctx) };
|
|
||||||
|
|
||||||
Ok(typed_func)
|
|
||||||
} else {
|
|
||||||
Err(ResolveError::ExportWrongType {
|
|
||||||
name: name.to_string(),
|
|
||||||
}
|
|
||||||
.into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve a function by name.
|
/// Resolve a function by name.
|
||||||
@ -292,37 +225,7 @@ impl Instance {
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn dyn_func(&self, name: &str) -> ResolveResult<DynFunc> {
|
pub fn dyn_func(&self, name: &str) -> ResolveResult<DynFunc> {
|
||||||
let export_index =
|
dyn_func(&*self.module, &self.inner, name)
|
||||||
self.module
|
|
||||||
.info
|
|
||||||
.exports
|
|
||||||
.get(name)
|
|
||||||
.ok_or_else(|| ResolveError::ExportNotFound {
|
|
||||||
name: name.to_string(),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if let ExportIndex::Func(func_index) = export_index {
|
|
||||||
let sig_index = *self
|
|
||||||
.module
|
|
||||||
.info
|
|
||||||
.func_assoc
|
|
||||||
.get(*func_index)
|
|
||||||
.expect("broken invariant, incorrect func index");
|
|
||||||
let signature =
|
|
||||||
SigRegistry.lookup_signature_ref(&self.module.info.signatures[sig_index]);
|
|
||||||
|
|
||||||
Ok(DynFunc {
|
|
||||||
signature,
|
|
||||||
module: &self.module,
|
|
||||||
instance_inner: &self.inner,
|
|
||||||
func_index: *func_index,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Err(ResolveError::ExportWrongType {
|
|
||||||
name: name.to_string(),
|
|
||||||
}
|
|
||||||
.into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call an exported WebAssembly function given the export name.
|
/// Call an exported WebAssembly function given the export name.
|
||||||
@ -419,6 +322,124 @@ impl Instance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Private function implementing the inner logic of `Instance::func`
|
||||||
|
// TODO: reevaluate this lifetime
|
||||||
|
fn func<'a, Args, Rets>(
|
||||||
|
module: &'a ModuleInner,
|
||||||
|
inst_inner: &'a InstanceInner,
|
||||||
|
name: &str,
|
||||||
|
) -> ResolveResult<Func<'a, Args, Rets, Wasm>>
|
||||||
|
where
|
||||||
|
Args: WasmTypeList,
|
||||||
|
Rets: WasmTypeList,
|
||||||
|
{
|
||||||
|
let export_index =
|
||||||
|
module
|
||||||
|
.info
|
||||||
|
.exports
|
||||||
|
.get(name)
|
||||||
|
.ok_or_else(|| ResolveError::ExportNotFound {
|
||||||
|
name: name.to_string(),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if let ExportIndex::Func(func_index) = export_index {
|
||||||
|
let sig_index = *module
|
||||||
|
.info
|
||||||
|
.func_assoc
|
||||||
|
.get(*func_index)
|
||||||
|
.expect("broken invariant, incorrect func index");
|
||||||
|
let signature = SigRegistry.lookup_signature_ref(&module.info.signatures[sig_index]);
|
||||||
|
|
||||||
|
if signature.params() != Args::types() || signature.returns() != Rets::types() {
|
||||||
|
Err(ResolveError::Signature {
|
||||||
|
expected: (*signature).clone(),
|
||||||
|
found: Args::types().to_vec(),
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ctx = match func_index.local_or_import(&module.info) {
|
||||||
|
LocalOrImport::Local(_) => inst_inner.vmctx,
|
||||||
|
LocalOrImport::Import(imported_func_index) => unsafe {
|
||||||
|
inst_inner.import_backing.vm_functions[imported_func_index]
|
||||||
|
.func_ctx
|
||||||
|
.as_ref()
|
||||||
|
}
|
||||||
|
.vmctx
|
||||||
|
.as_ptr(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let func_wasm_inner = module
|
||||||
|
.runnable_module
|
||||||
|
.get_trampoline(&module.info, sig_index)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let (func_ptr, func_env) = match func_index.local_or_import(&module.info) {
|
||||||
|
LocalOrImport::Local(local_func_index) => (
|
||||||
|
module
|
||||||
|
.runnable_module
|
||||||
|
.get_func(&module.info, local_func_index)
|
||||||
|
.unwrap(),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
LocalOrImport::Import(import_func_index) => {
|
||||||
|
let imported_func = &inst_inner.import_backing.vm_functions[import_func_index];
|
||||||
|
|
||||||
|
(
|
||||||
|
NonNull::new(imported_func.func as *mut _).unwrap(),
|
||||||
|
unsafe { imported_func.func_ctx.as_ref() }.func_env,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let typed_func: Func<Args, Rets, Wasm> =
|
||||||
|
unsafe { Func::from_raw_parts(func_wasm_inner, func_ptr, func_env, ctx) };
|
||||||
|
|
||||||
|
Ok(typed_func)
|
||||||
|
} else {
|
||||||
|
Err(ResolveError::ExportWrongType {
|
||||||
|
name: name.to_string(),
|
||||||
|
}
|
||||||
|
.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Private function implementing the inner logic of `Instance::dyn_func`
|
||||||
|
fn dyn_func<'a>(
|
||||||
|
module: &'a ModuleInner,
|
||||||
|
inst_inner: &'a InstanceInner,
|
||||||
|
name: &str,
|
||||||
|
) -> ResolveResult<DynFunc<'a>> {
|
||||||
|
let export_index =
|
||||||
|
module
|
||||||
|
.info
|
||||||
|
.exports
|
||||||
|
.get(name)
|
||||||
|
.ok_or_else(|| ResolveError::ExportNotFound {
|
||||||
|
name: name.to_string(),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if let ExportIndex::Func(func_index) = export_index {
|
||||||
|
let sig_index = *module
|
||||||
|
.info
|
||||||
|
.func_assoc
|
||||||
|
.get(*func_index)
|
||||||
|
.expect("broken invariant, incorrect func index");
|
||||||
|
let signature = SigRegistry.lookup_signature_ref(&module.info.signatures[sig_index]);
|
||||||
|
|
||||||
|
Ok(DynFunc {
|
||||||
|
signature,
|
||||||
|
module: &module,
|
||||||
|
instance_inner: &inst_inner,
|
||||||
|
func_index: *func_index,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err(ResolveError::ExportWrongType {
|
||||||
|
name: name.to_string(),
|
||||||
|
}
|
||||||
|
.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl InstanceInner {
|
impl InstanceInner {
|
||||||
pub(crate) fn get_export_from_index(
|
pub(crate) fn get_export_from_index(
|
||||||
&self,
|
&self,
|
||||||
@ -823,11 +844,11 @@ impl<'a> DynFunc<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Exportable<'a> for Memory {
|
impl<'a> Exportable<'a> for Memory {
|
||||||
fn get_self(instance: &'a Instance, name: &str) -> Option<Self> {
|
fn get_self(exports: &'a Exports, name: &str) -> Option<Self> {
|
||||||
let export_index = instance.module.info.exports.get(name)?;
|
let (inst_inner, module) = exports.get_inner();
|
||||||
|
let export_index = module.info.exports.get(name)?;
|
||||||
if let ExportIndex::Memory(idx) = export_index {
|
if let ExportIndex::Memory(idx) = export_index {
|
||||||
let module = instance.module.borrow();
|
Some(inst_inner.get_memory_from_index(module, *idx))
|
||||||
Some(instance.inner.get_memory_from_index(module, *idx))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -835,11 +856,11 @@ impl<'a> Exportable<'a> for Memory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Exportable<'a> for Table {
|
impl<'a> Exportable<'a> for Table {
|
||||||
fn get_self(instance: &'a Instance, name: &str) -> Option<Self> {
|
fn get_self(exports: &'a Exports, name: &str) -> Option<Self> {
|
||||||
let export_index = instance.module.info.exports.get(name)?;
|
let (inst_inner, module) = exports.get_inner();
|
||||||
|
let export_index = module.info.exports.get(name)?;
|
||||||
if let ExportIndex::Table(idx) = export_index {
|
if let ExportIndex::Table(idx) = export_index {
|
||||||
let module = instance.module.borrow();
|
Some(inst_inner.get_table_from_index(module, *idx))
|
||||||
Some(instance.inner.get_table_from_index(module, *idx))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -847,11 +868,11 @@ impl<'a> Exportable<'a> for Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Exportable<'a> for Global {
|
impl<'a> Exportable<'a> for Global {
|
||||||
fn get_self(instance: &'a Instance, name: &str) -> Option<Self> {
|
fn get_self(exports: &'a Exports, name: &str) -> Option<Self> {
|
||||||
let export_index = instance.module.info.exports.get(name)?;
|
let (inst_inner, module) = exports.get_inner();
|
||||||
|
let export_index = module.info.exports.get(name)?;
|
||||||
if let ExportIndex::Global(idx) = export_index {
|
if let ExportIndex::Global(idx) = export_index {
|
||||||
let module = instance.module.borrow();
|
Some(inst_inner.get_global_from_index(module, *idx))
|
||||||
Some(instance.inner.get_global_from_index(module, *idx))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -859,26 +880,33 @@ impl<'a> Exportable<'a> for Global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Exportable<'a> for DynFunc<'a> {
|
impl<'a> Exportable<'a> for DynFunc<'a> {
|
||||||
fn get_self(instance: &'a Instance, name: &str) -> Option<Self> {
|
fn get_self(exports: &'a Exports, name: &str) -> Option<Self> {
|
||||||
instance.dyn_func(name).ok()
|
let (inst_inner, module) = exports.get_inner();
|
||||||
|
dyn_func(module, inst_inner, name).ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Args: WasmTypeList, Rets: WasmTypeList> Exportable<'a> for Func<'a, Args, Rets, Wasm> {
|
impl<'a, Args: WasmTypeList, Rets: WasmTypeList> Exportable<'a> for Func<'a, Args, Rets, Wasm> {
|
||||||
fn get_self(instance: &'a Instance, name: &str) -> Option<Self> {
|
fn get_self(exports: &'a Exports, name: &str) -> Option<Self> {
|
||||||
instance.func(name).ok()
|
let (inst_inner, module) = exports.get_inner();
|
||||||
|
func(module, inst_inner, name).ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Exports` is used to get exports like [`Func`]s, [`DynFunc`]s, [`Memory`]s,
|
/// `Exports` is used to get exports like [`Func`]s, [`DynFunc`]s, [`Memory`]s,
|
||||||
/// [`Global`]s, and [`Table`]s from an [`Instance`].
|
/// [`Global`]s, and [`Table`]s from an [`Instance`].
|
||||||
///
|
///
|
||||||
/// Use [`Instance::exports_new`] to get an `Exports` from an [`Instance`].
|
/// Use `Instance.exports` to get an `Exports` from an [`Instance`].
|
||||||
pub struct Exports<'a> {
|
pub struct Exports {
|
||||||
instance: &'a Instance,
|
// We want to avoid the borrow checker here.
|
||||||
|
// This is safe because
|
||||||
|
// 1. `Exports` can't be constructed or copied (so can't safely outlive `Instance`)
|
||||||
|
// 2. `InstanceInner` is `Pin<Box<>>`, thus we know that it will not move.
|
||||||
|
instance_inner: *const InstanceInner,
|
||||||
|
module: Arc<ModuleInner>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Exports<'a> {
|
impl Exports {
|
||||||
/// Get an export.
|
/// Get an export.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
@ -887,21 +915,28 @@ impl<'a> Exports<'a> {
|
|||||||
/// # use wasmer_runtime_core::types::Value;
|
/// # use wasmer_runtime_core::types::Value;
|
||||||
/// # fn example_fn(instance: &Instance) -> Option<()> {
|
/// # fn example_fn(instance: &Instance) -> Option<()> {
|
||||||
/// // We can get a function as a static `Func`
|
/// // We can get a function as a static `Func`
|
||||||
/// let func: Func<i32, i32> = instance.exports_new().get("my_func")?;
|
/// let func: Func<i32, i32> = instance.exports.get("my_func")?;
|
||||||
/// let _result = func.call(42);
|
/// let _result = func.call(42);
|
||||||
///
|
///
|
||||||
/// // Or we can get it as a dynamic `DynFunc`
|
/// // Or we can get it as a dynamic `DynFunc`
|
||||||
/// let dyn_func: DynFunc = instance.exports_new().get("my_func")?;
|
/// let dyn_func: DynFunc = instance.exports.get("my_func")?;
|
||||||
/// let _result= dyn_func.call(&[Value::I32(42)]);
|
/// let _result= dyn_func.call(&[Value::I32(42)]);
|
||||||
///
|
///
|
||||||
/// // We can also get other exports like `Global`s, `Memory`s, and `Table`s
|
/// // We can also get other exports like `Global`s, `Memory`s, and `Table`s
|
||||||
/// let _counter: Global = instance.exports_new().get("counter")?;
|
/// let _counter: Global = instance.exports.get("counter")?;
|
||||||
///
|
///
|
||||||
/// # Some(())
|
/// # Some(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn get<T: Exportable<'a>>(&self, name: &str) -> Option<T> {
|
pub fn get<'a, T: Exportable<'a>>(&'a self, name: &str) -> Option<T> {
|
||||||
T::get_self(self.instance, name)
|
T::get_self(self, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This method must remain private.
|
||||||
|
fn get_inner(&self) -> (&InstanceInner, &ModuleInner) {
|
||||||
|
let inst_inner = unsafe { &*self.instance_inner };
|
||||||
|
let module = self.module.borrow();
|
||||||
|
(inst_inner, module)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user