Rust Bindings for LittlevGL

Hi all,

I just wanted to share that I have started to write safe bindings for Rust to use LittlevGL. This project makes it easy and idiomatic to write LittlevGL based applications in Rust.

The project is still in it’s initial state, but I was able to actually run in an embedded device and see the widgets.

I have also available in the repo, examples of the library working with a simulator. Having a simulator makes it possible to write and run your projects in Rust using lvgl-rs in your desktop, then use the exact same code to run on your embedded device (taken you’ve abstracted everything that is not dependent on hardware).

Let me know what you think. I am happy to accept contributions! :slight_smile:
I hope you will enjoy!

2 Likes

That’s amazing!

How do you create the binding? Do you have a script or do it manually?

1 Like

Thank you!

It’s mostly a manual process.

The way to start is to use rust-bindgen tool to generate the “low level” code that binds to the exported interface of the C library. That generated binding is “unsafe” as it can only be called inside unsafe {} blocks in Rust. That is the only generated part and the starting point of the process.

After that, we need to craft manually the safe & idiomatic Rust API on top of the unsafe bindings. That’s where a lot of manual work and attention needs to be invested. We need to translate the C library types to Rust types and all the other guarantees, like if the library is not safe to use in threaded environments, etc.

I was heavily inspired by this blog post. Also I saw that most of the PineTime opensource OSs were already using LVGL and there was no Rust bindings available yet. So I decided to create the LVGL Rust bindings library. :slight_smile:

It is still very much a work in progress, but it already works for the widgets that are implemented. Yesterday, I finished upgrading it to the new style system of LVGL 7.

All the help is welcome, in case you or anyone wants to participate. It is a hobby project for me as I’m not a full-time embedded developer. I really like embedded development and Rust, so I like to play with that whenever I get some free time.

I would like to participate as I’m new to Rust and learn more easily while doing. Do you have some sort of TODO list?

Hey @Carlos_Diaz! That’s awesome you want to join. We have a long to do list, as LVGL supports so many widgets we need to create the Rust API for them.

You can see the list here https://github.com/rafaelcaricio/lvgl-rs#widgets The widgets not marked are the missing ones. So you can see how to start by looking at the lvgl-rs/src/widgets folder. A simple example is the Gauge widget. You can see also we created a Rust enum for the parts, that should be also created for the widget you choose to create, if they have parts. You can start and open a PR when you have something and we can continue from there. :wink:

1 Like

The widget code looks like it could be generated automatically. It might be worth exploring this avenue more before committing to several hours of manual work.

I’ve never used Rust before, but the set_value argument types map directly to the equivalent C99 integer types, and the enum logic also looks easy to template. We’d just need a suitable C parser (the MicroPython bindings script uses https://github.com/eliben/pycparser, I don’t know if you are familiar with the Rust counterpart).

1 Like

Yeah, actually now looking at the code to reply to @Carlos_Diaz I realised that many code parts seem duplicated right now. So I simplified greatly the code necessary to port the widgets. Now to port the btn just just:

define_object!(Btn, lv_btn_create);

I also changed the name convention to follow exactly LVGL code.

I will look into also creating a macro for the enum conversions. Probably that can also be automated. That is a good idea. I will look closer at the Python port as well.

I did start some rudimentary code generation based directly on the C99 code. It could also be solved with Rust procedural macros, but IDEs don’t have auto-complete support for it yet. So I decided to just generate raw code. Another motivation was also that the rust-bindgen do not convert C macros to Rust.

@ioctl
Glad to hear that you already integrated the new styles system. :rocket:

I think, by “The widget code looks like it could be generated automatically” @embeddedt meant that, it’s possible to run a script on the source code of LVGL, parse it and automatically generate the binding’s code.

It has the advantages of

  1. Less initial work: should be faster than manually writing binding to all functions
  2. Less error-prone: can avoid human error
  3. Easier maintenance: just run the script again on a new version of LVGL to create the new binding

I think once you have explored how the binding could work, the task for binding generation is mainly to find a suitable C parser library (e.g. pycparser), get familiar with it and utilize it. What do you think about it?

Having a new binding to LVGL would be awesome and very welcome! If you want we can open a new repo for it in lvgl organization, and officially promote it once it’s ready.

1 Like

Sure, generation for most of the code is the path I’m pursuing now. Makes a lot of sense. I’m trying some different approaches for the code generation and will be able to release something soon™️.

Great! :slight_smile: Please keep us updated!

I just wanted to give a quick update. I was playing around to make the LVGL Rust bindings able to compile to WASM and run on the browser. Here is the live example working: https://rafaelcaricio.github.io/lvgl-rs-wasm/
It is a simple example as LVGL Rust bindings are still in development.

The source code for anyone interested is available here: https://github.com/rafaelcaricio/lvgl-rs-wasm

Thank you for the update! It’s pretty cool!

How do you create the binding now? Generate with a script or manually?

Hi @kisvegabor I’m writing rust code to auto-generate the bindings for Rust based on the LVGL C API.
Sorry for the late reply. I’m working on the project in my free time, so it is taking a while… :slight_smile: But I will get there.

No problem, let us know if you have any questions :slight_smile:

1 Like

This is such a fantastic work! Thanks a lot for starting this! Can you let us know if you need some specific help on anything urgently? I want to make sure we have full LVGL support on Rust asap.

2 Likes

Thank you for the message @audiores ! Messages like this really motivates me to continue the work. I’m currently focusing on reviewing the Rust bindings API and the code generation piece. I’m working on the branch api-review, making the Rust bindings usage more ergonomic and flexible.

I would like to rely as much as possible on code generation, so I’m getting some inspiration from gir and gtk-rs-core projects on that part. The main challenges right now are:

  • Extracting as much information as possible from the LVGL public C API (ownership of memory space, if an allocation should be made on the caller side or LVGL side, lifetime of a pointed memory location, etc);
  • Mapping what are the most important public API functions we need to have bindings to.

Nothing is urgent in the project for me. :slight_smile: I’m just trying to have fun and using this project to learn more about low level programming and Rust.

The project is usable at this point, probably you would want to look into the input device PR that I have open. I didn’t merge that PR because I’m not satisfied with the API design I came up there, so I want to try a different approach after I do this API review.

If you want to help on something cool, I would recommend this ticket #11. It is about supporting a *.toml file to configure LVGL and hide the existence of the *.h LVGL config file. I think it would help greatly people to avoid making mistakes and abstract the configuration of LVGL in a more familiar format for Rust developers. I also recommend this issue because it wouldn’t conflict with the work I’m doing right now. :slight_smile: Let me know if you want to work on this, and I can give you some of the ideas I have to solve this ticket.

If you wish we can open an issue to discuss the Rust binding on GitHub too. This way more developer of LVGL might see it.

2 Likes

@kisvegabor That would be awesome! :slight_smile:

Feel free to open the issue :slight_smile: