Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to call dart functions in rust? #443

Closed
m-haisham opened this issue May 6, 2022 · 17 comments
Closed

How to call dart functions in rust? #443

m-haisham opened this issue May 6, 2022 · 17 comments
Labels
wontfix This will not be worked on

Comments

@m-haisham
Copy link

I noticed the documentation was missing how a dart function can be called in rust.

@welcome
Copy link

welcome bot commented May 6, 2022

Hi! Thanks for opening your first issue here! 😄

@fzyzcjy
Copy link
Owner

fzyzcjy commented May 6, 2022

This is not directly supported yet, but you can always use some callback-map-like approach. Feel free to make a PR!

@m-haisham
Copy link
Author

callback-map-like approach

Could you perhaps describe this approach.

@shekohex
Copy link

You can look here (https://github.com/sunshine-protocol/frusty-logger) at how you can do that, I made a log crate compatible logger that works with flutter and dart.
So, in Rust the log crate you can build/implement the back-end logging, and I made a way to bind the print and debugPrint from dart to rust, so rust whenever you use log::info!("....") it will call the print function in dart.

@thomas725
Copy link
Contributor

thomas725 commented Jun 6, 2022

Hi there! I'm new to flutter+dart & rust. I'd like to be able to log from rust to flutter.

As far as I understand it, http://cjycode.com/flutter_rust_bridge/feature/stream.html is the basis best used for that purpose.

@fzyzcjy wrote about including a logging facility directly into the flutter_rust_bridge here: #348
But said it was blocked by the same reason as cancelable tasks: #333 (comment)

I did manage to incoperate @Desdaemon's example from https://gist.github.com/Desdaemon/be5da0a1c6b4724f20093ef434959744 into my playground app.

Since the counter starts from 0 again every time I get back to the page where I display it, I'm quite certain I created a memory leak with this, because as discussed @ #347 the Rust side doesn't know when Dart stops listening and keeps on churning out integers anyway. And Flutter creates new instances whenever that page get's opened again.

Also from that sample I don't see how I could push data into that sink from other places in my rust code, outside of the tick function.

There is an incomplete "Simplified for demonstration" example for pushing LogEntries from Rust to Dart @ http://cjycode.com/flutter_rust_bridge/feature/stream.html - But I couldn't find out yet how to use OnceCell or Mutex or RwLock to get that sample to compile & run. There are some more snippets @ #398 but I can't use OnceCell like @LambdaMan2K as this seems to be an unstable feature you would need to switch to the nightly Rust compiler for (which I'd prefer not to as a Rust newbie..)

I also cloned https://github.com/sunshine-protocol/frusty-logger referenced by @shekohex but could neither get it running nor understand how it should work. Also I'd prefer a minimal sample that helps me understand the basics to using a library.

Can somebody help please? Thank you!

@fzyzcjy
Copy link
Owner

fzyzcjy commented Jun 6, 2022

@thomas725 Let's discuss in #486 since I guess this is a common question people may face.

@thomas725
Copy link
Contributor

thomas725 commented Jun 9, 2022

Thank you @fzyzcjy for documenting your rust->flutter logging setup and allowing me to copy it :)

A question concerning the more generic topic of this thread: If I use a Stream to get data continuously generated in a loop in rust (as in @Desdaemon's gist) into flutter for displaying, how can I make the rust loop stop, when the flutter screen displaying the data is closed?

@fzyzcjy
Copy link
Owner

fzyzcjy commented Jun 9, 2022

how can I make the rust loop stop

I guess not supported yet? Feel free to make a PR!

@shekohex
Copy link

shekohex commented Jun 9, 2022

how can I make the rust loop stop, when the flutter screen displaying the data is closed?

Try using an atomic bool, and expose a function from Rust to dart to set the value of it to be false. so that in your loop in each iteration you check if you should stop or not.

@thomas725
Copy link
Contributor

@shekohex yes, I thought of something like that too, but where in flutter do I put the call to rust to set that "continue" boolean to false? All the code on the flutter side for my screen is in a method Widget build(BuildContext context). Is there a deconstructor or something like that which I can override?

@shekohex
Copy link

shekohex commented Jun 9, 2022

I guess depends on your code, but the dispose method on the state should do it.

@thomas725
Copy link
Contributor

thomas725 commented Jun 9, 2022

@shekohex thank you, exactly what I've been looking for!

Now how do I write this in rust without the compiler complaining that it's unsafe and telling me I need an unsafe block whenever I access KEEP_TICKING?

static mut KEEP_TICKING: bool = false;

// can't omit the return type yet, this is a bug
pub fn tick(sink: StreamSink<u16>) -> Result<()> {
    let mut ticks = 0;
    KEEP_TICKING = true;
    while KEEP_TICKING {
        sink.add(ticks);
        info!("sunk tick: {}", ticks);
        sleep(ONE_SECOND);
        if ticks == u16::MAX {
            break;
        }
        ticks += 1;
    }
    Ok(())
}

pub fn stopTicking() {
    KEEP_TICKING = false;
}

@shekohex
Copy link

shekohex commented Jun 9, 2022

Do not use just bool you will need to use AtomicBool and also remove mut from that, static mut is not good IMO.

@thomas725
Copy link
Contributor

thomas725 commented Jun 9, 2022

Ah, okey, thanks for the hint!

EDIT: I think now I got it:

static KEEP_TICKING: AtomicBool = AtomicBool::new(false);

// can't omit the return type yet, this is a bug
pub fn tick(sink: StreamSink<u16>) -> Result<()> {
    let mut ticks = 0;
    KEEP_TICKING.store(true, Ordering::Relaxed);
    while KEEP_TICKING.load(Ordering::Relaxed) {
        sink.add(ticks);
        info!("sunk tick: {}", ticks);
        sleep(ONE_SECOND);
        if ticks == u16::MAX {
            break;
        }
        ticks += 1;
    }
    Ok(())
}

pub fn stopTicking() {
    KEEP_TICKING.store(false, Ordering::Relaxed);
}

@fzyzcjy
Copy link
Owner

fzyzcjy commented Jun 9, 2022

IMHO you should use store(https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html#method.store) requires &self and does atomic things internally. The get_mut requires &mut self instead of doing real atomic operations.

@stale
Copy link

stale bot commented Aug 8, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix This will not be worked on label Aug 8, 2022
@stale stale bot closed this as completed Aug 15, 2022
@github-actions
Copy link
Contributor

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 30, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

4 participants