mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-07 13:18:20 +00:00
Added support for native calls to dynamic functions
This commit is contained in:
34
lib/api/src/externals/function.rs
vendored
34
lib/api/src/externals/function.rs
vendored
@@ -9,7 +9,7 @@ use std::cmp::max;
|
|||||||
use wasm_common::{HostFunction, WasmTypeList, WithEnv, WithoutEnv};
|
use wasm_common::{HostFunction, WasmTypeList, WithEnv, WithoutEnv};
|
||||||
use wasmer_runtime::{
|
use wasmer_runtime::{
|
||||||
wasmer_call_trampoline, Export, ExportFunction, VMCallerCheckedAnyfunc, VMContext,
|
wasmer_call_trampoline, Export, ExportFunction, VMCallerCheckedAnyfunc, VMContext,
|
||||||
VMDynamicFunctionImportContext, VMFunctionBody, VMFunctionKind, VMTrampoline,
|
VMDynamicFunctionContext, VMFunctionBody, VMFunctionKind, VMTrampoline,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A function defined in the Wasm module
|
/// A function defined in the Wasm module
|
||||||
@@ -35,6 +35,7 @@ pub struct Function {
|
|||||||
pub(crate) definition: FunctionDefinition,
|
pub(crate) definition: FunctionDefinition,
|
||||||
// If the Function is owned by the Store, not the instance
|
// If the Function is owned by the Store, not the instance
|
||||||
pub(crate) owned_by_store: bool,
|
pub(crate) owned_by_store: bool,
|
||||||
|
pub(crate) has_env: bool,
|
||||||
pub(crate) exported: ExportFunction,
|
pub(crate) exported: ExportFunction,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,6 +59,7 @@ impl Function {
|
|||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
owned_by_store: true,
|
owned_by_store: true,
|
||||||
definition: FunctionDefinition::Host,
|
definition: FunctionDefinition::Host,
|
||||||
|
has_env: false,
|
||||||
exported: ExportFunction {
|
exported: ExportFunction {
|
||||||
address,
|
address,
|
||||||
vmctx,
|
vmctx,
|
||||||
@@ -72,17 +74,20 @@ impl Function {
|
|||||||
where
|
where
|
||||||
F: Fn(&[Val]) -> Result<Vec<Val>, RuntimeError> + 'static,
|
F: Fn(&[Val]) -> Result<Vec<Val>, RuntimeError> + 'static,
|
||||||
{
|
{
|
||||||
let dynamic_ctx =
|
let dynamic_ctx = VMDynamicFunctionContext::from_context(VMDynamicFunctionWithoutEnv {
|
||||||
VMDynamicFunctionImportContext::from_context(VMDynamicFunctionWithoutEnv {
|
|
||||||
func: Box::new(func),
|
func: Box::new(func),
|
||||||
function_type: ty.clone(),
|
function_type: ty.clone(),
|
||||||
});
|
});
|
||||||
|
// We don't yet have the address with the Wasm ABI signature.
|
||||||
|
// The engine linker will replace the address with one pointing to a
|
||||||
|
// generated dynamic trampoline.
|
||||||
let address = std::ptr::null() as *const VMFunctionBody;
|
let address = std::ptr::null() as *const VMFunctionBody;
|
||||||
let vmctx = Box::into_raw(Box::new(dynamic_ctx)) as *mut VMContext;
|
let vmctx = Box::into_raw(Box::new(dynamic_ctx)) as *mut VMContext;
|
||||||
Self {
|
Self {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
owned_by_store: true,
|
owned_by_store: true,
|
||||||
definition: FunctionDefinition::Host,
|
definition: FunctionDefinition::Host,
|
||||||
|
has_env: false,
|
||||||
exported: ExportFunction {
|
exported: ExportFunction {
|
||||||
address,
|
address,
|
||||||
kind: VMFunctionKind::Dynamic,
|
kind: VMFunctionKind::Dynamic,
|
||||||
@@ -98,17 +103,21 @@ impl Function {
|
|||||||
F: Fn(&mut Env, &[Val]) -> Result<Vec<Val>, RuntimeError> + 'static,
|
F: Fn(&mut Env, &[Val]) -> Result<Vec<Val>, RuntimeError> + 'static,
|
||||||
Env: Sized,
|
Env: Sized,
|
||||||
{
|
{
|
||||||
let dynamic_ctx = VMDynamicFunctionImportContext::from_context(VMDynamicFunctionWithEnv {
|
let dynamic_ctx = VMDynamicFunctionContext::from_context(VMDynamicFunctionWithEnv {
|
||||||
env,
|
env,
|
||||||
func: Box::new(func),
|
func: Box::new(func),
|
||||||
function_type: ty.clone(),
|
function_type: ty.clone(),
|
||||||
});
|
});
|
||||||
|
// We don't yet have the address with the Wasm ABI signature.
|
||||||
|
// The engine linker will replace the address with one pointing to a
|
||||||
|
// generated dynamic trampoline.
|
||||||
let address = std::ptr::null() as *const VMFunctionBody;
|
let address = std::ptr::null() as *const VMFunctionBody;
|
||||||
let vmctx = Box::into_raw(Box::new(dynamic_ctx)) as *mut VMContext;
|
let vmctx = Box::into_raw(Box::new(dynamic_ctx)) as *mut VMContext;
|
||||||
Self {
|
Self {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
owned_by_store: true,
|
owned_by_store: true,
|
||||||
definition: FunctionDefinition::Host,
|
definition: FunctionDefinition::Host,
|
||||||
|
has_env: true,
|
||||||
exported: ExportFunction {
|
exported: ExportFunction {
|
||||||
address,
|
address,
|
||||||
kind: VMFunctionKind::Dynamic,
|
kind: VMFunctionKind::Dynamic,
|
||||||
@@ -143,6 +152,7 @@ impl Function {
|
|||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
owned_by_store: true,
|
owned_by_store: true,
|
||||||
definition: FunctionDefinition::Host,
|
definition: FunctionDefinition::Host,
|
||||||
|
has_env: true,
|
||||||
exported: ExportFunction {
|
exported: ExportFunction {
|
||||||
address,
|
address,
|
||||||
kind: VMFunctionKind::Static,
|
kind: VMFunctionKind::Static,
|
||||||
@@ -269,6 +279,7 @@ impl Function {
|
|||||||
Self {
|
Self {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
owned_by_store: false,
|
owned_by_store: false,
|
||||||
|
has_env: true,
|
||||||
definition: FunctionDefinition::Wasm(WasmFunctionDefinition { trampoline }),
|
definition: FunctionDefinition::Wasm(WasmFunctionDefinition { trampoline }),
|
||||||
exported: wasmer_export,
|
exported: wasmer_export,
|
||||||
}
|
}
|
||||||
@@ -307,6 +318,7 @@ impl Function {
|
|||||||
self.exported.vmctx,
|
self.exported.vmctx,
|
||||||
self.exported.kind,
|
self.exported.kind,
|
||||||
self.definition.clone(),
|
self.definition.clone(),
|
||||||
|
self.has_env,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -330,12 +342,12 @@ impl std::fmt::Debug for Function {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This trait is one that all dynamic functions must fulfill.
|
/// This trait is one that all dynamic functions must fulfill.
|
||||||
trait VMDynamicFunction {
|
pub(crate) trait VMDynamicFunction {
|
||||||
fn call(&self, args: &[Val]) -> Result<Vec<Val>, RuntimeError>;
|
fn call(&self, args: &[Val]) -> Result<Vec<Val>, RuntimeError>;
|
||||||
fn function_type(&self) -> &FunctionType;
|
fn function_type(&self) -> &FunctionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VMDynamicFunctionWithoutEnv {
|
pub(crate) struct VMDynamicFunctionWithoutEnv {
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
func: Box<dyn Fn(&[Val]) -> Result<Vec<Val>, RuntimeError> + 'static>,
|
func: Box<dyn Fn(&[Val]) -> Result<Vec<Val>, RuntimeError> + 'static>,
|
||||||
function_type: FunctionType,
|
function_type: FunctionType,
|
||||||
@@ -350,7 +362,7 @@ impl VMDynamicFunction for VMDynamicFunctionWithoutEnv {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VMDynamicFunctionWithEnv<Env>
|
pub(crate) struct VMDynamicFunctionWithEnv<Env>
|
||||||
where
|
where
|
||||||
Env: Sized,
|
Env: Sized,
|
||||||
{
|
{
|
||||||
@@ -372,13 +384,13 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait VMDynamicFunctionImportCall<T: VMDynamicFunction> {
|
trait VMDynamicFunctionCall<T: VMDynamicFunction> {
|
||||||
fn from_context(ctx: T) -> Self;
|
fn from_context(ctx: T) -> Self;
|
||||||
fn address_ptr() -> *const VMFunctionBody;
|
fn address_ptr() -> *const VMFunctionBody;
|
||||||
unsafe fn func_wrapper(&self, values_vec: *mut i128);
|
unsafe fn func_wrapper(&self, values_vec: *mut i128);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: VMDynamicFunction> VMDynamicFunctionImportCall<T> for VMDynamicFunctionImportContext<T> {
|
impl<T: VMDynamicFunction> VMDynamicFunctionCall<T> for VMDynamicFunctionContext<T> {
|
||||||
fn from_context(ctx: T) -> Self {
|
fn from_context(ctx: T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
address: Self::address_ptr(),
|
address: Self::address_ptr(),
|
||||||
@@ -393,8 +405,8 @@ impl<T: VMDynamicFunction> VMDynamicFunctionImportCall<T> for VMDynamicFunctionI
|
|||||||
// This function wraps our func, to make it compatible with the
|
// This function wraps our func, to make it compatible with the
|
||||||
// reverse trampoline signature
|
// reverse trampoline signature
|
||||||
unsafe fn func_wrapper(
|
unsafe fn func_wrapper(
|
||||||
// Note: we use the trick that the first param to this function is the `VMDynamicFunctionImportContext`
|
// Note: we use the trick that the first param to this function is the `VMDynamicFunctionContext`
|
||||||
// itself, so rather than doing `dynamic_ctx: &VMDynamicFunctionImportContext<T>`, we simplify it a bit
|
// itself, so rather than doing `dynamic_ctx: &VMDynamicFunctionContext<T>`, we simplify it a bit
|
||||||
&self,
|
&self,
|
||||||
values_vec: *mut i128,
|
values_vec: *mut i128,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -9,11 +9,14 @@
|
|||||||
//! ```
|
//! ```
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use crate::externals::function::{FunctionDefinition, WasmFunctionDefinition};
|
use crate::externals::function::{
|
||||||
|
FunctionDefinition, VMDynamicFunction, VMDynamicFunctionWithoutEnv, WasmFunctionDefinition,
|
||||||
|
};
|
||||||
use crate::{Function, FunctionType, RuntimeError, Store};
|
use crate::{Function, FunctionType, RuntimeError, Store};
|
||||||
use wasm_common::{NativeWasmType, WasmExternType, WasmTypeList};
|
use wasm_common::{NativeWasmType, WasmExternType, WasmTypeList};
|
||||||
use wasmer_runtime::{
|
use wasmer_runtime::{
|
||||||
wasmer_call_trampoline, ExportFunction, VMContext, VMFunctionBody, VMFunctionKind,
|
wasmer_call_trampoline, ExportFunction, VMContext, VMDynamicFunctionContext, VMFunctionBody,
|
||||||
|
VMFunctionKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct NativeFunc<'a, Args = (), Rets = ()> {
|
pub struct NativeFunc<'a, Args = (), Rets = ()> {
|
||||||
@@ -22,6 +25,7 @@ pub struct NativeFunc<'a, Args = (), Rets = ()> {
|
|||||||
address: *const VMFunctionBody,
|
address: *const VMFunctionBody,
|
||||||
vmctx: *mut VMContext,
|
vmctx: *mut VMContext,
|
||||||
arg_kind: VMFunctionKind,
|
arg_kind: VMFunctionKind,
|
||||||
|
has_env: bool,
|
||||||
// exported: ExportFunction,
|
// exported: ExportFunction,
|
||||||
_phantom: PhantomData<(&'a (), Args, Rets)>,
|
_phantom: PhantomData<(&'a (), Args, Rets)>,
|
||||||
}
|
}
|
||||||
@@ -39,6 +43,7 @@ where
|
|||||||
vmctx: *mut VMContext,
|
vmctx: *mut VMContext,
|
||||||
arg_kind: VMFunctionKind,
|
arg_kind: VMFunctionKind,
|
||||||
definition: FunctionDefinition,
|
definition: FunctionDefinition,
|
||||||
|
has_env: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
definition,
|
definition,
|
||||||
@@ -46,6 +51,7 @@ where
|
|||||||
address,
|
address,
|
||||||
vmctx,
|
vmctx,
|
||||||
arg_kind,
|
arg_kind,
|
||||||
|
has_env,
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,6 +84,7 @@ where
|
|||||||
store: other.store,
|
store: other.store,
|
||||||
definition: other.definition,
|
definition: other.definition,
|
||||||
owned_by_store: true, // todo
|
owned_by_store: true, // todo
|
||||||
|
has_env: other.has_env,
|
||||||
exported: ExportFunction {
|
exported: ExportFunction {
|
||||||
address: other.address,
|
address: other.address,
|
||||||
vmctx: other.vmctx,
|
vmctx: other.vmctx,
|
||||||
@@ -169,7 +176,21 @@ macro_rules! impl_native_traits {
|
|||||||
return Ok(results);
|
return Ok(results);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
todo!("dynamic host functions not yet implemented")
|
/// Is a dynamic function
|
||||||
|
if !self.has_env {
|
||||||
|
let ctx = self.vmctx as *mut VMDynamicFunctionContext<VMDynamicFunctionWithoutEnv>;
|
||||||
|
let params_list = [ $( $x.to_native().to_value() ),* ];
|
||||||
|
let results = unsafe { (*ctx).ctx.call(¶ms_list)? };
|
||||||
|
let mut rets_list_array = Rets::empty_array();
|
||||||
|
let mut_rets = rets_list_array.as_mut() as *mut [i128] as *mut i128;
|
||||||
|
for (i, ret) in results.iter().enumerate() {
|
||||||
|
unsafe {
|
||||||
|
ret.write_value_to(mut_rets.add(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(Rets::from_array(rets_list_array));
|
||||||
|
}
|
||||||
|
unimplemented!("native calls to dynamic function with env not yet implemented");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ pub use crate::sig_registry::SignatureRegistry;
|
|||||||
pub use crate::table::{Table, TableElements, TablePlan, TableStyle};
|
pub use crate::table::{Table, TableElements, TablePlan, TableStyle};
|
||||||
pub use crate::trap::*;
|
pub use crate::trap::*;
|
||||||
pub use crate::vmcontext::{
|
pub use crate::vmcontext::{
|
||||||
VMBuiltinFunctionIndex, VMCallerCheckedAnyfunc, VMContext, VMDynamicFunctionImportContext,
|
VMBuiltinFunctionIndex, VMCallerCheckedAnyfunc, VMContext, VMDynamicFunctionContext,
|
||||||
VMFunctionBody, VMFunctionImport, VMFunctionKind, VMGlobalDefinition, VMGlobalImport,
|
VMFunctionBody, VMFunctionImport, VMFunctionKind, VMGlobalDefinition, VMGlobalImport,
|
||||||
VMMemoryDefinition, VMMemoryImport, VMSharedSignatureIndex, VMTableDefinition, VMTableImport,
|
VMMemoryDefinition, VMMemoryImport, VMSharedSignatureIndex, VMTableDefinition, VMTableImport,
|
||||||
VMTrampoline,
|
VMTrampoline,
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ mod test_vmfunction_import {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The `VMDynamicFunctionImportContext` is the context that dynamic
|
/// The `VMDynamicFunctionContext` is the context that dynamic
|
||||||
/// functions will receive when called (rather than `vmctx`).
|
/// functions will receive when called (rather than `vmctx`).
|
||||||
/// A dynamic function is a function for which we don't know the signature
|
/// A dynamic function is a function for which we don't know the signature
|
||||||
/// until runtime.
|
/// until runtime.
|
||||||
@@ -55,7 +55,7 @@ mod test_vmfunction_import {
|
|||||||
/// containing the relevant context for running the function indicated
|
/// containing the relevant context for running the function indicated
|
||||||
/// in `address`.
|
/// in `address`.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct VMDynamicFunctionImportContext<T: Sized> {
|
pub struct VMDynamicFunctionContext<T: Sized> {
|
||||||
/// The address of the inner dynamic function.
|
/// The address of the inner dynamic function.
|
||||||
///
|
///
|
||||||
/// Note: The function must be on the form of
|
/// Note: The function must be on the form of
|
||||||
@@ -68,7 +68,7 @@ pub struct VMDynamicFunctionImportContext<T: Sized> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_vmdynamicfunction_import_context {
|
mod test_vmdynamicfunction_import_context {
|
||||||
use super::VMDynamicFunctionImportContext;
|
use super::VMDynamicFunctionContext;
|
||||||
use crate::{ModuleInfo, VMOffsets};
|
use crate::{ModuleInfo, VMOffsets};
|
||||||
use memoffset::offset_of;
|
use memoffset::offset_of;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
@@ -78,15 +78,15 @@ mod test_vmdynamicfunction_import_context {
|
|||||||
let module = ModuleInfo::new();
|
let module = ModuleInfo::new();
|
||||||
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
|
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
size_of::<VMDynamicFunctionImportContext<usize>>(),
|
size_of::<VMDynamicFunctionContext<usize>>(),
|
||||||
usize::from(offsets.size_of_vmdynamicfunction_import_context())
|
usize::from(offsets.size_of_vmdynamicfunction_import_context())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
offset_of!(VMDynamicFunctionImportContext<usize>, address),
|
offset_of!(VMDynamicFunctionContext<usize>, address),
|
||||||
usize::from(offsets.vmdynamicfunction_import_context_address())
|
usize::from(offsets.vmdynamicfunction_import_context_address())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
offset_of!(VMDynamicFunctionImportContext<usize>, ctx),
|
offset_of!(VMDynamicFunctionContext<usize>, ctx),
|
||||||
usize::from(offsets.vmdynamicfunction_import_context_ctx())
|
usize::from(offsets.vmdynamicfunction_import_context_ctx())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,9 +110,9 @@ impl VMOffsets {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Offsets for [`VMDynamicFunctionImportContext`].
|
/// Offsets for [`VMDynamicFunctionContext`].
|
||||||
///
|
///
|
||||||
/// [`VMDynamicFunctionImportContext`]: crate::vmcontext::VMDynamicFunctionImportContext
|
/// [`VMDynamicFunctionContext`]: crate::vmcontext::VMDynamicFunctionContext
|
||||||
impl VMOffsets {
|
impl VMOffsets {
|
||||||
/// The offset of the `address` field.
|
/// The offset of the `address` field.
|
||||||
#[allow(clippy::erasing_op)]
|
#[allow(clippy::erasing_op)]
|
||||||
@@ -126,9 +126,9 @@ impl VMOffsets {
|
|||||||
1 * self.pointer_size
|
1 * self.pointer_size
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the size of [`VMDynamicFunctionImportContext`].
|
/// Return the size of [`VMDynamicFunctionContext`].
|
||||||
///
|
///
|
||||||
/// [`VMDynamicFunctionImportContext`]: crate::vmcontext::VMDynamicFunctionImportContext
|
/// [`VMDynamicFunctionContext`]: crate::vmcontext::VMDynamicFunctionContext
|
||||||
pub fn size_of_vmdynamicfunction_import_context(&self) -> u8 {
|
pub fn size_of_vmdynamicfunction_import_context(&self) -> u8 {
|
||||||
2 * self.pointer_size
|
2 * self.pointer_size
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
//! easily in Rust, thanks to it's advanced typing system.
|
//! easily in Rust, thanks to it's advanced typing system.
|
||||||
|
|
||||||
use crate::types::{FunctionType, Type};
|
use crate::types::{FunctionType, Type};
|
||||||
|
use crate::values::Value;
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
@@ -34,6 +35,15 @@ pub trait NativeWasmType {
|
|||||||
/// Convert self to i128 binary representation.
|
/// Convert self to i128 binary representation.
|
||||||
fn to_binary(self) -> i128;
|
fn to_binary(self) -> i128;
|
||||||
|
|
||||||
|
/// Convert self to a `Value`
|
||||||
|
fn to_value<T>(self) -> Value<T>
|
||||||
|
where
|
||||||
|
Self: std::marker::Sized,
|
||||||
|
{
|
||||||
|
let binary = self.to_binary();
|
||||||
|
unsafe { Value::read_value_from(&binary, Self::WASM_TYPE) }
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert to self from i128 binary representation.
|
/// Convert to self from i128 binary representation.
|
||||||
fn from_binary(binary: i128) -> Self;
|
fn from_binary(binary: i128) -> Self;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,6 +199,30 @@ impl<T> From<AnyRef> for Value<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Into<i32> for Value<T> {
|
||||||
|
fn into(self) -> i32 {
|
||||||
|
self.unwrap_i32()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Into<i64> for Value<T> {
|
||||||
|
fn into(self) -> i64 {
|
||||||
|
self.unwrap_i64()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Into<f32> for Value<T> {
|
||||||
|
fn into(self) -> f32 {
|
||||||
|
self.unwrap_f32()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Into<f64> for Value<T> {
|
||||||
|
fn into(self) -> f64 {
|
||||||
|
self.unwrap_f64()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// impl<T> From<T> for Value<T> {
|
// impl<T> From<T> for Value<T> {
|
||||||
// fn from(val: T) -> Self {
|
// fn from(val: T) -> Self {
|
||||||
// Self::FuncRef(val)
|
// Self::FuncRef(val)
|
||||||
|
|||||||
@@ -39,3 +39,32 @@ fn native_function_works_for_wasm() -> Result<()> {
|
|||||||
assert_eq!(result, 20);
|
assert_eq!(result, 20);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dynamic_raw_call_no_env() -> anyhow::Result<()> {
|
||||||
|
let store = get_store();
|
||||||
|
let reverse_duplicate = wasmer::Function::new_dynamic(
|
||||||
|
&store,
|
||||||
|
&wasmer::FunctionType::new(
|
||||||
|
vec![
|
||||||
|
wasmer::ValType::I32,
|
||||||
|
wasmer::ValType::I64,
|
||||||
|
wasmer::ValType::F32,
|
||||||
|
wasmer::ValType::F64,
|
||||||
|
],
|
||||||
|
vec![wasmer::ValType::F64],
|
||||||
|
),
|
||||||
|
|values| {
|
||||||
|
Ok(vec![
|
||||||
|
Value::F64(values[3].unwrap_f64() * 2.0),
|
||||||
|
Value::F32(values[2].unwrap_f32() * 2.0),
|
||||||
|
Value::I64(values[2].unwrap_i64() * 2.0),
|
||||||
|
Value::I32(values[2].unwrap_i32() * 2.0),
|
||||||
|
])
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let reverse_duplicate_native: NativeFunc<(i32, i64, f32, f64), (f64, f32, i64, i32)> =
|
||||||
|
reverse_duplicate.native().unwrap();
|
||||||
|
let result = reverse_duplicate_native.call(1, 3, 5.0, 7.0)?;
|
||||||
|
assert_eq!(result, (14.0, 10.0, 6, 2));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -67,11 +67,12 @@ macro_rules! mvr_test {
|
|||||||
fn dynamic() -> anyhow::Result<()> {
|
fn dynamic() -> anyhow::Result<()> {
|
||||||
let store = get_store();
|
let store = get_store();
|
||||||
let module = get_module(&store)?;
|
let module = get_module(&store)?;
|
||||||
|
let callback_fn = wasmer::Function::new_dynamic(&store, &wasmer::FunctionType::new(vec![wasmer::ValType::I32], vec![ $( <$result_type>::expected_valtype() ),* ]), dynamic_callback_fn);
|
||||||
let instance = wasmer::Instance::new(
|
let instance = wasmer::Instance::new(
|
||||||
&module,
|
&module,
|
||||||
&wasmer::imports! {
|
&wasmer::imports! {
|
||||||
"host" => {
|
"host" => {
|
||||||
"callback_fn" => wasmer::Function::new_dynamic(&store, &wasmer::FunctionType::new(vec![wasmer::ValType::I32], vec![ $( <$result_type>::expected_valtype() ),* ]), dynamic_callback_fn)
|
"callback_fn" => callback_fn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)?;
|
)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user