lvgl / lv_binding_rust

LVGL bindings for Rust. A powerful and easy-to-use embedded GUI with many widgets, advanced visual effects (opacity, antialiasing, animations) and low memory requirements (16K RAM, 64K Flash).
MIT License
687 stars 71 forks source link

Auto-initialize LVGL #79

Closed nia-e closed 1 year ago

nia-e commented 1 year ago

As discussed in #69, the current API can cause UB if not used properly. The option of using static_init to auto-initialize was agreed on, though I opted for ctor since it does the same thing but seems better-maintained. I added a feature also to gate disabling this behaviour, along with a huge disclaimer as to why it shouldn't be used.

Closes #69

rafaelcaricio commented 1 year ago

Is ctor able to be used in no_std environments?

rafaelcaricio commented 1 year ago

Probably a good path moving forward would be to use https://doc.rust-lang.org/core/cell/struct.LazyCell.html once it is stable.

nia-e commented 1 year ago

Is ctor able to be used in no_std environments?

Yes! ctor has no hard dependency on basically anything, and is also quite platform-agnostic. I did stumble upon several examples of it being used in no-std environments, such as this example gist

Probably a good path moving forward would be to use https://doc.rust-lang.org/core/cell/struct.LazyCell.html once it is stable.

Ideally yes, but I figured fixing this now is the highest priority (especially since it's hard to tell if an error is caused; there's no obvious "you forgot to init LVGL" error message). Once LazyCell is stable, we should use that

nia-e commented 1 year ago

The one restriction ctor has is that the target must have a linker, but LVGL doesn't support complete baremetal anyways so this shouldn't be an issue.

nia-e commented 1 year ago

Digging in, seems like LazyCell isn't ideal for what we want. It can't be a static since those must be Sync (and only LazyLock implements it, but LazyLock is std-only) and there's no obvious way to do it without... resorting to ctor again :c

rafaelcaricio commented 1 year ago

but LVGL doesn't support complete baremetal anyways so this shouldn't be an issue.

I'm confused, LVGL is literally used in microcontrollers thus baremetal. What do you mean it "does not complete support baremetal"?

nia-e commented 1 year ago

Ah, sorry. I misinterpreted the thread - I took it to mean that LVGL requires a framebuffer to be set up, but I realize that was meant only for RPi. The linker requirement of ctor does become a pain point then - but static_init has even stricter requirements (e.g. only supporting no-std on linux). Should I revert this merge? Or I can just document that for baremetal the auto-initialization must be disabled

rafaelcaricio commented 1 year ago

Maybe we can use the spin crate https://github.com/mvdnes/spin-rs the spin::Lazy seems like what we want? It seems suitable for no_std environments and use spin locks which don't need OS primitives.

nia-e commented 1 year ago

Just tried it out. Seems to not work; it only initializes when the static is actually accessed. I guess we could have a dummy let _ = INIT; in every function? But that sort of sends us back to maintainability hell

nia-e commented 1 year ago

This thread seems to suggest the best way to do what we're doing is indeed ctor or maybe linkme

rafaelcaricio commented 1 year ago

Oh, right.... 😭

Alright, let's go with ctor then. I guess we need to document this, so people in baremetal will need to initialize themselves LVGL-rs.

nia-e commented 1 year ago

I'll send in a PR updating documentation then. Sorry :c

rafaelcaricio commented 1 year ago

No worries, I find it good to discuss this as it is important for the usage of this crate. Also, this kind of discussion was what I missed the most while working on this alone... so, thank you! 😄

nia-e commented 1 year ago

Glad this is fun :D I love messing with Rust so getting to commit eldritch abominations vaguely resembling code like I've been doing in my time here is a very engaging expenditure of time

rafaelcaricio commented 1 year ago

The important is to have fun in open-source! :))))) 🎸