PistonDevelopers / dyon

A rusty dynamically typed scripting language
Apache License 2.0
1.77k stars 55 forks source link

Passing data between two functions called from rust #653

Closed jice-nospam closed 4 years ago

jice-nospam commented 4 years ago

I'm trying to use dyon as a scripting language for a fantasy console coded in rust. The console calls a init() function defined in the script, then for each frame a render() function is called. How can I pass a context from the init function to the render function ? Using current object doesn't work because render is not called directly by init itself but by the rust part. My idea was to return a context from the init function that the rust engine had to pass as parameter to the render function, but the type is unknown at compile time.

bvssvni commented 4 years ago

You can use this library https://crates.io/crates/current

jice-nospam commented 4 years ago

As far as I understand, this library brings the dyon concept of current object to rust. My problem is that I don't have a Rust type for the object created by the dyon script.

Is there a way to get a sort of generic reference to a dyon created object and pass it as parameter to a dyon function ?

Basically, rust calls a init() dyon function that returns an object. This object depends on the script and is not known at compile time. Then rust must call a render() dyon function and pass this object as a parameter.

bvssvni commented 4 years ago

You can use Variable on the rust side, even if the type is unknown.

jice-nospam commented 4 years ago

Thank you, this works. However, I get an error if the parameter is mutable :

fn init() -> {} {
    println("init")
    return {t:0,r:1,g:1,b:1,c:1,s:1}
}

fn update(mut ctx) {
    println("update")
    ctx.t+=0.01
    ctx.c=cos(ctx.t)
    ctx.s=sin(ctx.t)
}

fn render(ctx) {
    gfx_line(40.0,40.0,40.0+ctx.c*20.0,40.0+ctx.s*20.0,1.0,0.0,0.0)
}

The render function is called and works. The update function though return an error : Could not find function 'update'

I'm calling it with

let call = Call::new("update").arg(self.var.clone());
error(call.run(&mut self.runtime, &self.module));

self.var being the Variable returned by the init function call.

jice-nospam commented 4 years ago

ok the trick was to Call::new("update(mut)")