How to register a rust function that can accept a rhai closure? #639
Unanswered
harudagondi
asked this question in
Q&A
Replies: 3 comments 16 replies
-
fn lfo(context: NativeCallContext, fp: FnPtr) -> Result<ReturnType, Box<EvalAltResult>> {
fp.call_within_context(&context, ...)
} |
Beta Was this translation helpful? Give feedback.
7 replies
-
This works: fn phaser(x: i64, callback: impl Fn(i64) -> i64) -> i64 {
callback(x)
}
let mut engine = Engine::new();
engine.register_fn("phaser", |context: NativeCallContext, x: i64, fp: FnPtr| {
// in a real application you'd not just 'unwrap' but you'd be handling errors
let callback = Box::new(|x| fp.call_within_context(&context, (x,)).unwrap());
phaser(x, callback)
});
assert_eq!(
engine.eval::<i64>("
const FACTOR = 2;
phaser(21, |x| x * FACTOR)
")?,
42
); However, it looks like you'd want to encapsulate that closure directly into the return value (what you call the "combinator"). |
Beta Was this translation helpful? Give feedback.
6 replies
-
This somewhats recreates what you want to do with use std::cell::RefCell;
use std::rc::Rc;
type SingleNode = Rc<dyn Node>;
trait Node {
fn run(&self, x: i64) -> i64;
}
struct PhaserNode {
func: Box<dyn Fn(i64) -> i64>,
}
impl Node for PhaserNode {
fn run(&self, x: i64) -> i64 {
(self.func)(x)
}
}
// say, this is fundsp's implementation of phaser with closure parameter
// that you'd like to call
fn phaser(callback: impl Fn(i64) -> i64 + 'static) -> impl Node {
PhaserNode {
func: Box::new(callback),
}
}
let mut engine = Engine::new();
let ast = Rc::new(engine.compile(
"
const FACTOR = 2;
phaser(|x| x * FACTOR)
",
)?);
let shared_engine = Rc::new(RefCell::new(Engine::new_raw())); // dummy Engine for now
let engine2 = shared_engine.clone();
let ast2 = ast.clone();
engine.register_fn("phaser", move |fp: FnPtr| {
let engine = engine2.clone();
let ast = ast2.clone();
let callback = Box::new(move |x: i64| fp.call(&engine.borrow(), &ast, (x,)).unwrap());
Rc::new(phaser(callback)) as SingleNode
});
// replace the dummy Engine with the real one
*shared_engine.borrow_mut() = engine;
// run the script and get back a node
let cb = shared_engine.borrow().eval_ast::<SingleNode>(&ast)?;
// that node can be run
assert_eq!(cb.run(21), 42); |
Beta Was this translation helpful? Give feedback.
3 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
I am writing a library that exposes
fundsp
as a rhai module, and I don't know how to register a rust function that can accept a rhai closure. It seems that the rhai book does not mention how to do this.For example, I want to register a function that looks like this:
(
hacker32
is just a prelude, and Box is clonable)How exactly do you do this for this situation?
Beta Was this translation helpful? Give feedback.
All reactions