diff --git a/RELEASES.md b/RELEASES.md index 1818519e..8a17c106 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -24,9 +24,11 @@ New features This is particularly useful when converting a Rust `struct` to a `Dynamic` _object map_ and back. * `Engine::disable_symbol` to surgically disable keywords and/or operators. * `Engine::register_custom_operator` to define a custom operator. -* New low-level API `Engine::register_raw_fn`. +* New low-level API `Engine::register_raw_fn` and `Engine::register_raw_fn_XXX`. +* New low-level API `Module::set_raw_fn` mirroring `Engine::register_raw_fn`. * `AST::clone_functions_only`, `AST::clone_functions_only_filtered` and `AST::clone_statements_only` to clone only part of an `AST`. * The boolean `^` (XOR) operator is added. +* `FnPtr` is exposed as the function pointer type. Version 0.16.1 diff --git a/src/api.rs b/src/api.rs index 5df12aba..a6500443 100644 --- a/src/api.rs +++ b/src/api.rs @@ -6,7 +6,7 @@ use crate::error::ParseError; use crate::fn_call::FuncArgs; use crate::fn_native::{IteratorFn, SendSync}; use crate::fn_register::RegisterFn; -use crate::module::Module; +use crate::module::{FuncReturn, Module}; use crate::optimize::{optimize_into_ast, OptimizationLevel}; use crate::parser::AST; use crate::result::EvalAltResult; @@ -39,30 +39,23 @@ impl Engine { /// /// This function is very low level. It takes a list of `TypeId`'s indicating the actual types of the parameters. /// - /// Arguments are simply passed in as a mutable array of `&mut Dynamic`. + /// Arguments are simply passed in as a mutable array of `&mut Dynamic`, /// The arguments are guaranteed to be of the correct types matching the `TypeId`'s. /// - /// To get access to a primary parameter value (i.e. cloning is cheap), use: `args[n].clone().cast::()` + /// To access a primary parameter value (i.e. cloning is cheap), use: `args[n].clone().cast::()` /// - /// To get access to a parameter value and avoid cloning, use `std::mem::take(args[n]).cast::()`. + /// To access a parameter value and avoid cloning, use `std::mem::take(args[n]).cast::()`. /// Notice that this will _consume_ the argument, replacing it with `()`. /// - /// To get access to the first mutable parameter, use `args.get_mut(0).unwrap()` + /// To access the first mutable parameter, use `args.get_mut(0).unwrap()` #[deprecated(note = "this function is volatile and may change")] - pub fn register_raw_fn( + pub fn register_raw_fn( &mut self, name: &str, arg_types: &[TypeId], - - #[cfg(not(feature = "sync"))] func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> Result> - + 'static, - - #[cfg(feature = "sync")] func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> Result> - + Send - + Sync - + 'static, + func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> FuncReturn + SendSync + 'static, ) { - self.global_module.set_fn_var_args(name, arg_types, func); + self.global_module.set_raw_fn(name, arg_types, func); } /// Register a function of no parameters with the `Engine`. @@ -71,19 +64,12 @@ impl Engine { /// /// This function is very low level. #[deprecated(note = "this function is volatile and may change")] - pub fn register_raw_fn_0( + pub fn register_raw_fn_0( &mut self, name: &str, - - #[cfg(not(feature = "sync"))] func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> Result> - + 'static, - - #[cfg(feature = "sync")] func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> Result> - + Send - + Sync - + 'static, + func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> FuncReturn + SendSync + 'static, ) { - self.global_module.set_fn_var_args(name, &[], func); + self.global_module.set_raw_fn(name, &[], func); } /// Register a function of one parameter with the `Engine`. @@ -92,30 +78,23 @@ impl Engine { /// /// This function is very low level. /// - /// Arguments are simply passed in as a mutable array of `&mut Dynamic`. - /// The argument is guaranteed to be of the correct type. + /// Arguments are simply passed in as a mutable array of `&mut Dynamic`, + /// which is guaranteed to contain enough arguments of the correct types. /// - /// To get access to a primary parameter value (i.e. cloning is cheap), use: `args[n].clone().cast::()` + /// To access a primary parameter value (i.e. cloning is cheap), use: `args[n].clone().cast::()` /// - /// To get access to a parameter value and avoid cloning, use `std::mem::take(args[n]).cast::()`. + /// To access a parameter value and avoid cloning, use `std::mem::take(args[n]).cast::()`. /// Notice that this will _consume_ the argument, replacing it with `()`. /// - /// To get access to the first mutable parameter, use `args.get_mut(0).unwrap()` + /// To access the first mutable parameter, use `args.get_mut(0).unwrap()` #[deprecated(note = "this function is volatile and may change")] - pub fn register_raw_fn_1( + pub fn register_raw_fn_1( &mut self, name: &str, - - #[cfg(not(feature = "sync"))] func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> Result> - + 'static, - - #[cfg(feature = "sync")] func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> Result> - + Send - + Sync - + 'static, + func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> FuncReturn + SendSync + 'static, ) { self.global_module - .set_fn_var_args(name, &[TypeId::of::()], func); + .set_raw_fn(name, &[TypeId::of::()], func); } /// Register a function of two parameters with the `Engine`. @@ -124,30 +103,23 @@ impl Engine { /// /// This function is very low level. /// - /// Arguments are simply passed in as a mutable array of `&mut Dynamic`. - /// The arguments are guaranteed to be of the correct types. + /// Arguments are simply passed in as a mutable array of `&mut Dynamic`, + /// which is guaranteed to contain enough arguments of the correct types. /// - /// To get access to a primary parameter value (i.e. cloning is cheap), use: `args[n].clone().cast::()` + /// To access a primary parameter value (i.e. cloning is cheap), use: `args[n].clone().cast::()` /// - /// To get access to a parameter value and avoid cloning, use `std::mem::take(args[n]).cast::()`. + /// To access a parameter value and avoid cloning, use `std::mem::take(args[n]).cast::()`. /// Notice that this will _consume_ the argument, replacing it with `()`. /// - /// To get access to the first mutable parameter, use `args.get_mut(0).unwrap()` + /// To access the first mutable parameter, use `args.get_mut(0).unwrap()` #[deprecated(note = "this function is volatile and may change")] - pub fn register_raw_fn_2( + pub fn register_raw_fn_2( &mut self, name: &str, - - #[cfg(not(feature = "sync"))] func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> Result> - + 'static, - - #[cfg(feature = "sync")] func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> Result> - + Send - + Sync - + 'static, + func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> FuncReturn + SendSync + 'static, ) { self.global_module - .set_fn_var_args(name, &[TypeId::of::(), TypeId::of::()], func); + .set_raw_fn(name, &[TypeId::of::(), TypeId::of::()], func); } /// Register a function of three parameters with the `Engine`. @@ -156,29 +128,27 @@ impl Engine { /// /// This function is very low level. /// - /// Arguments are simply passed in as a mutable array of `&mut Dynamic`. - /// The arguments are guaranteed to be of the correct types. + /// Arguments are simply passed in as a mutable array of `&mut Dynamic`, + /// which is guaranteed to contain enough arguments of the correct types. /// - /// To get access to a primary parameter value (i.e. cloning is cheap), use: `args[n].clone().cast::()` + /// To access a primary parameter value (i.e. cloning is cheap), use: `args[n].clone().cast::()` /// - /// To get access to a parameter value and avoid cloning, use `std::mem::take(args[n]).cast::()`. + /// To access a parameter value and avoid cloning, use `std::mem::take(args[n]).cast::()`. /// Notice that this will _consume_ the argument, replacing it with `()`. /// - /// To get access to the first mutable parameter, use `args.get_mut(0).unwrap()` + /// To access the first mutable parameter, use `args.get_mut(0).unwrap()` #[deprecated(note = "this function is volatile and may change")] - pub fn register_raw_fn_3( + pub fn register_raw_fn_3< + A: Variant + Clone, + B: Variant + Clone, + C: Variant + Clone, + T: Variant + Clone, + >( &mut self, name: &str, - - #[cfg(not(feature = "sync"))] func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> Result> - + 'static, - - #[cfg(feature = "sync")] func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> Result> - + Send - + Sync - + 'static, + func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> FuncReturn + SendSync + 'static, ) { - self.global_module.set_fn_var_args( + self.global_module.set_raw_fn( name, &[TypeId::of::(), TypeId::of::(), TypeId::of::()], func, @@ -191,34 +161,28 @@ impl Engine { /// /// This function is very low level. /// - /// Arguments are simply passed in as a mutable array of `&mut Dynamic`. - /// The arguments are guaranteed to be of the correct types. + /// Arguments are simply passed in as a mutable array of `&mut Dynamic`, + /// which is guaranteed to contain enough arguments of the correct types. /// - /// To get access to a primary parameter value (i.e. cloning is cheap), use: `args[n].clone().cast::()` + /// To access a primary parameter value (i.e. cloning is cheap), use: `args[n].clone().cast::()` /// - /// To get access to a parameter value and avoid cloning, use `std::mem::take(args[n]).cast::()`. + /// To access a parameter value and avoid cloning, use `std::mem::take(args[n]).cast::()`. /// Notice that this will _consume_ the argument, replacing it with `()`. /// - /// To get access to the first mutable parameter, use `args.get_mut(0).unwrap()` + /// To access the first mutable parameter, use `args.get_mut(0).unwrap()` #[deprecated(note = "this function is volatile and may change")] pub fn register_raw_fn_4< A: Variant + Clone, B: Variant + Clone, C: Variant + Clone, D: Variant + Clone, + T: Variant + Clone, >( &mut self, name: &str, - - #[cfg(not(feature = "sync"))] func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> Result> - + 'static, - - #[cfg(feature = "sync")] func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> Result> - + Send - + Sync - + 'static, + func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> FuncReturn + SendSync + 'static, ) { - self.global_module.set_fn_var_args( + self.global_module.set_raw_fn( name, &[ TypeId::of::(), @@ -1395,7 +1359,7 @@ impl Engine { name: &str, mut this_ptr: Option<&mut Dynamic>, mut arg_values: impl AsMut<[Dynamic]>, - ) -> Result> { + ) -> FuncReturn { self.call_fn_dynamic_raw(scope, lib, name, &mut this_ptr, arg_values.as_mut()) } @@ -1415,7 +1379,7 @@ impl Engine { name: &str, this_ptr: &mut Option<&mut Dynamic>, arg_values: &mut [Dynamic], - ) -> Result> { + ) -> FuncReturn { let lib = lib.as_ref(); let mut args: StaticVec<_> = arg_values.iter_mut().collect(); let fn_def = diff --git a/src/module.rs b/src/module.rs index cd08e5bc..9703552b 100644 --- a/src/module.rs +++ b/src/module.rs @@ -3,7 +3,7 @@ use crate::any::{Dynamic, Variant}; use crate::calc_fn_hash; use crate::engine::{make_getter, make_setter, Engine, Imports, FN_IDX_GET, FN_IDX_SET}; -use crate::fn_native::{CallableFunction, FnCallArgs, IteratorFn, SendSync, Shared}; +use crate::fn_native::{CallableFunction as Func, FnCallArgs, IteratorFn, SendSync, Shared}; use crate::parser::{ FnAccess, FnAccess::{Private, Public}, @@ -49,18 +49,14 @@ pub struct Module { all_variables: HashMap, /// External Rust functions. - functions: HashMap< - u64, - (String, FnAccess, StaticVec, CallableFunction), - StraightHasherBuilder, - >, + functions: HashMap, Func), StraightHasherBuilder>, /// Iterator functions, keyed by the type producing the iterator. type_iterators: HashMap, /// Flattened collection of all external Rust functions, native or scripted, /// including those in sub-modules. - all_functions: HashMap, + all_functions: HashMap, /// Is the module indexed? indexed: bool, @@ -346,18 +342,18 @@ impl Module { /// Set a Rust function into the module, returning a hash key. /// /// If there is an existing Rust function of the same hash, it is replaced. - pub fn set_fn( + pub(crate) fn set_fn( &mut self, name: impl Into, access: FnAccess, - params: &[TypeId], - func: CallableFunction, + arg_types: &[TypeId], + func: Func, ) -> u64 { let name = name.into(); - let hash_fn = calc_fn_hash(empty(), &name, params.len(), params.iter().cloned()); + let hash_fn = calc_fn_hash(empty(), &name, arg_types.len(), arg_types.iter().cloned()); - let params = params.into_iter().cloned().collect(); + let params = arg_types.into_iter().cloned().collect(); self.functions .insert(hash_fn, (name, access, params, func.into())); @@ -367,29 +363,72 @@ impl Module { hash_fn } - /// Set a Rust function taking a reference to the scripting `Engine`, plus a list of - /// mutable `Dynamic` references into the module, returning a hash key. - /// A list of `TypeId`'s is taken as the argument types. + /// Set a Rust function taking a reference to the scripting `Engine`, the current set of functions, + /// plus a list of mutable `Dynamic` references into the module, returning a hash key. /// /// Use this to register a built-in function which must reference settings on the scripting - /// `Engine` (e.g. to prevent growing an array beyond the allowed maximum size). + /// `Engine` (e.g. to prevent growing an array beyond the allowed maximum size), or to call a + /// script-defined function in the current evaluation context. /// /// If there is a similar existing Rust function, it is replaced. - pub(crate) fn set_fn_var_args( + /// + /// ## WARNING - Low Level API + /// + /// This function is very low level. + /// + /// A list of `TypeId`'s is taken as the argument types. + /// + /// Arguments are simply passed in as a mutable array of `&mut Dynamic`, + /// which is guaranteed to contain enough arguments of the correct types. + /// + /// To access a primary parameter value (i.e. cloning is cheap), use: `args[n].clone().cast::()` + /// + /// To access a parameter value and avoid cloning, use `std::mem::take(args[n]).cast::()`. + /// Notice that this will _consume_ the argument, replacing it with `()`. + /// + /// To access the first mutable parameter, use `args.get_mut(0).unwrap()` + /// + /// # Examples + /// + /// ``` + /// use rhai::Module; + /// + /// let mut module = Module::new(); + /// let hash = module.set_raw_fn("double_or_not", + /// // Pass parameter types via a slice with TypeId's + /// &[std::any::TypeId::of::(), std::any::TypeId::of::() ], + /// // Fixed closure signature + /// |engine, lib, args| { + /// // 'args' is guaranteed to be the right length and of the correct types + /// + /// // Get the second parameter by 'consuming' it + /// let double = std::mem::take(args[1]).cast::(); + /// // Since it is a primary type, it can also be cheaply copied + /// let double = args[1].clone().cast::(); + /// // Get a mutable reference to the first argument. + /// let x = args[0].downcast_mut::().unwrap(); + /// + /// let orig = *x; + /// + /// if double { + /// *x *= 2; // the first argument can be mutated + /// } + /// + /// Ok(orig) // return Result> + /// }); + /// + /// assert!(module.contains_fn(hash)); + /// ``` + pub fn set_raw_fn( &mut self, name: impl Into, - args: &[TypeId], + arg_types: &[TypeId], func: impl Fn(&Engine, &Module, &mut [&mut Dynamic]) -> FuncReturn + SendSync + 'static, ) -> u64 { let f = move |engine: &Engine, lib: &Module, args: &mut FnCallArgs| { func(engine, lib, args).map(Dynamic::from) }; - self.set_fn( - name, - Public, - args, - CallableFunction::from_method(Box::new(f)), - ) + self.set_fn(name, Public, arg_types, Func::from_method(Box::new(f))) } /// Set a Rust function taking no parameters into the module, returning a hash key. @@ -411,13 +450,8 @@ impl Module { func: impl Fn() -> FuncReturn + SendSync + 'static, ) -> u64 { let f = move |_: &Engine, _: &Module, _: &mut FnCallArgs| func().map(Dynamic::from); - let args = []; - self.set_fn( - name, - Public, - &args, - CallableFunction::from_pure(Box::new(f)), - ) + let arg_types = []; + self.set_fn(name, Public, &arg_types, Func::from_pure(Box::new(f))) } /// Set a Rust function taking one parameter into the module, returning a hash key. @@ -441,13 +475,8 @@ impl Module { let f = move |_: &Engine, _: &Module, args: &mut FnCallArgs| { func(mem::take(args[0]).cast::()).map(Dynamic::from) }; - let args = [TypeId::of::()]; - self.set_fn( - name, - Public, - &args, - CallableFunction::from_pure(Box::new(f)), - ) + let arg_types = [TypeId::of::()]; + self.set_fn(name, Public, &arg_types, Func::from_pure(Box::new(f))) } /// Set a Rust function taking one mutable parameter into the module, returning a hash key. @@ -471,13 +500,8 @@ impl Module { let f = move |_: &Engine, _: &Module, args: &mut FnCallArgs| { func(args[0].downcast_mut::().unwrap()).map(Dynamic::from) }; - let args = [TypeId::of::()]; - self.set_fn( - name, - Public, - &args, - CallableFunction::from_method(Box::new(f)), - ) + let arg_types = [TypeId::of::()]; + self.set_fn(name, Public, &arg_types, Func::from_method(Box::new(f))) } /// Set a Rust getter function taking one mutable parameter, returning a hash key. @@ -528,13 +552,8 @@ impl Module { func(a, b).map(Dynamic::from) }; - let args = [TypeId::of::(), TypeId::of::()]; - self.set_fn( - name, - Public, - &args, - CallableFunction::from_pure(Box::new(f)), - ) + let arg_types = [TypeId::of::(), TypeId::of::()]; + self.set_fn(name, Public, &arg_types, Func::from_pure(Box::new(f))) } /// Set a Rust function taking two parameters (the first one mutable) into the module, @@ -564,13 +583,8 @@ impl Module { func(a, b).map(Dynamic::from) }; - let args = [TypeId::of::(), TypeId::of::()]; - self.set_fn( - name, - Public, - &args, - CallableFunction::from_method(Box::new(f)), - ) + let arg_types = [TypeId::of::(), TypeId::of::()]; + self.set_fn(name, Public, &arg_types, Func::from_method(Box::new(f))) } /// Set a Rust setter function taking two parameters (the first one mutable) into the module, @@ -656,13 +670,8 @@ impl Module { func(a, b, c).map(Dynamic::from) }; - let args = [TypeId::of::(), TypeId::of::(), TypeId::of::()]; - self.set_fn( - name, - Public, - &args, - CallableFunction::from_pure(Box::new(f)), - ) + let arg_types = [TypeId::of::(), TypeId::of::(), TypeId::of::()]; + self.set_fn(name, Public, &arg_types, Func::from_pure(Box::new(f))) } /// Set a Rust function taking three parameters (the first one mutable) into the module, @@ -698,13 +707,8 @@ impl Module { func(a, b, c).map(Dynamic::from) }; - let args = [TypeId::of::(), TypeId::of::(), TypeId::of::()]; - self.set_fn( - name, - Public, - &args, - CallableFunction::from_method(Box::new(f)), - ) + let arg_types = [TypeId::of::(), TypeId::of::(), TypeId::of::()]; + self.set_fn(name, Public, &arg_types, Func::from_method(Box::new(f))) } /// Set a Rust index setter taking three parameters (the first one mutable) into the module, @@ -735,12 +739,12 @@ impl Module { func(a, b, c).map(Dynamic::from) }; - let args = [TypeId::of::(), TypeId::of::(), TypeId::of::()]; + let arg_types = [TypeId::of::(), TypeId::of::(), TypeId::of::()]; self.set_fn( FN_IDX_SET, Public, - &args, - CallableFunction::from_method(Box::new(f)), + &arg_types, + Func::from_method(Box::new(f)), ) } @@ -778,18 +782,13 @@ impl Module { func(a, b, c, d).map(Dynamic::from) }; - let args = [ + let arg_types = [ TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), ]; - self.set_fn( - name, - Public, - &args, - CallableFunction::from_pure(Box::new(f)), - ) + self.set_fn(name, Public, &arg_types, Func::from_pure(Box::new(f))) } /// Set a Rust function taking four parameters (the first one mutable) into the module, @@ -827,25 +826,20 @@ impl Module { func(a, b, c, d).map(Dynamic::from) }; - let args = [ + let arg_types = [ TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), ]; - self.set_fn( - name, - Public, - &args, - CallableFunction::from_method(Box::new(f)), - ) + self.set_fn(name, Public, &arg_types, Func::from_method(Box::new(f))) } /// Get a Rust function. /// /// The `u64` hash is calculated by the function `crate::calc_fn_hash`. /// It is also returned by the `set_fn_XXX` calls. - pub(crate) fn get_fn(&self, hash_fn: u64) -> Option<&CallableFunction> { + pub(crate) fn get_fn(&self, hash_fn: u64) -> Option<&Func> { self.functions.get(&hash_fn).map(|(_, _, _, v)| v) } @@ -857,7 +851,7 @@ impl Module { pub(crate) fn get_qualified_fn( &mut self, hash_qualified_fn: u64, - ) -> Result<&CallableFunction, Box> { + ) -> Result<&Func, Box> { self.all_functions.get(&hash_qualified_fn).ok_or_else(|| { Box::new(EvalAltResult::ErrorFunctionNotFound( String::new(), @@ -886,9 +880,7 @@ impl Module { .iter() .filter(|(_, (_, _, _, v))| match v { #[cfg(not(feature = "no_function"))] - CallableFunction::Script(ref f) => { - filter(f.access, f.name.as_str(), f.params.len()) - } + Func::Script(ref f) => filter(f.access, f.name.as_str(), f.params.len()), _ => true, }) .map(|(&k, v)| (k, v.clone())), @@ -906,7 +898,7 @@ impl Module { #[cfg(not(feature = "no_function"))] pub(crate) fn retain_functions(&mut self, filter: impl Fn(FnAccess, &str, usize) -> bool) { self.functions.retain(|_, (_, _, _, v)| match v { - CallableFunction::Script(ref f) => filter(f.access, f.name.as_str(), f.params.len()), + Func::Script(ref f) => filter(f.access, f.name.as_str(), f.params.len()), _ => true, }); @@ -936,7 +928,7 @@ impl Module { /// Get an iterator to the functions in the module. pub(crate) fn iter_fn( &self, - ) -> impl Iterator, CallableFunction)> { + ) -> impl Iterator, Func)> { self.functions.values() } @@ -1003,7 +995,7 @@ impl Module { module: &'a Module, qualifiers: &mut Vec<&'a str>, variables: &mut Vec<(u64, Dynamic)>, - functions: &mut Vec<(u64, CallableFunction)>, + functions: &mut Vec<(u64, Func)>, ) { for (name, m) in &module.modules { // Index all the sub-modules first. diff --git a/src/packages/array_basic.rs b/src/packages/array_basic.rs index acaa1132..0a580933 100644 --- a/src/packages/array_basic.rs +++ b/src/packages/array_basic.rs @@ -67,7 +67,7 @@ macro_rules! reg_tri { macro_rules! reg_pad { ($lib:expr, $op:expr, $func:ident, $($par:ty),*) => { $({ - $lib.set_fn_var_args($op, + $lib.set_raw_fn($op, &[TypeId::of::(), TypeId::of::(), TypeId::of::<$par>()], $func::<$par> ); diff --git a/src/packages/string_more.rs b/src/packages/string_more.rs index 5ae39db6..248b0e93 100644 --- a/src/packages/string_more.rs +++ b/src/packages/string_more.rs @@ -223,7 +223,7 @@ def_package!(crate:MoreStringPackage:"Additional string utilities, including str Ok(()) }, ); - lib.set_fn_var_args( + lib.set_raw_fn( "pad", &[TypeId::of::(), TypeId::of::(), TypeId::of::()], |engine: &Engine, _: &Module, args: &mut [&mut Dynamic]| { diff --git a/tests/call_fn.rs b/tests/call_fn.rs index 715fbc87..62291830 100644 --- a/tests/call_fn.rs +++ b/tests/call_fn.rs @@ -1,7 +1,7 @@ #![cfg(not(feature = "no_function"))] use rhai::{ - Dynamic, Engine, EvalAltResult, Func, ImmutableString, Module, ParseError, ParseErrorType, - Scope, INT, + Dynamic, Engine, EvalAltResult, FnPtr, Func, ImmutableString, Module, ParseError, + ParseErrorType, Scope, INT, }; #[test] @@ -122,17 +122,23 @@ fn test_fn_ptr() -> Result<(), Box> { "bar", &[ std::any::TypeId::of::(), - std::any::TypeId::of::(), + std::any::TypeId::of::(), std::any::TypeId::of::(), ], move |engine: &Engine, lib: &Module, args: &mut [&mut Dynamic]| { - let callback = args[1].clone().cast::(); + let fp = std::mem::take(args[1]).cast::(); let value = args[2].clone(); let this_ptr = args.get_mut(0).unwrap(); - engine.call_fn_dynamic(&mut Scope::new(), lib, &callback, Some(this_ptr), [value])?; + engine.call_fn_dynamic( + &mut Scope::new(), + lib, + fp.fn_name(), + Some(this_ptr), + [value], + )?; - Ok(().into()) + Ok(()) }, ); @@ -142,7 +148,7 @@ fn test_fn_ptr() -> Result<(), Box> { fn foo(x) { this += x; } let x = 41; - x.bar("foo", 1); + x.bar(Fn("foo"), 1); x "# )?,