Itās so great to see! Iād really love to see a good C++ binding finally.
My only concern is maintainability. In order to easily follow LVGL API change we should generate the binding at least for the widgets. What do you think about it?
I can work on updating the API on each LVGL release. So each new lv release will support the newer API. I think itās easier and more direct than generating a bindings then generating code from that binding. The biggest work was already made on the architecture, which is now complete. Following changes and adding functions here and there is easy.
If someone spots anything lacking, I can add it very fast.
Please note that one of the decisions I took is to decay the C++ API into generating the same binary as if someone is directly using the C API. In order to not add additional problems and overhead by the new wrapper. If something works in C, it will in C++.
Iāve used a slightly updated version of vpaeder 8.3 version for a large embedded project based on Zephyr RTOS.
While deciding to port to 9.3 I wanted to ensure all samples made by vpaeder could be verifyed, and therefore I used the lv_port_pc_vscode project as base.
Oh thatās where vscode comes from. Are there more lv-ports?
Iāve just focused on lvglpp which ought be agnostic to development tools and platform
OK, I see that you updated the old c++ port, but I am not sure it has everything lvgl can do.
In my port, everything the C library can do is supported by the C++ wrapper, which disappear on compilation (zero-overhead), this means that it itself doesnāt add new errors or edge cases to the state of the original C library.
For the C++20, itās not just a random selection, I use C++ concepts for example that can catch non supported callback uses for example that diverge from what C library support.
Iāll have a look at your wrapper. Would be nice with just one being kept alive.
The vpaeder variant is zero overhead too Iād say. Only problem is a pointer to the real lvgl object which you sometime have to release ownership of, so it doesnāt get destructed when your cpp object destroys
This is a timely discussion which Iām happy to find. I also have a new C++ API targeting LVGL 9.4 here: GitHub - pedapudi/lvgl_cpp
The primary focus is on an updated API following idiomatic C++20 with strong typing, modularity, discoverability, and memory safety (including respecting LVGLās preferred management of objects). Ultimately, code is ready by humans, and the goal is to make it easy and fast to develop with LVGL. The API design without many āgotchasā to get things running smoothly is the objective. Making choices so that creature comforts like turnkey benchmarking and design choices that jive with modern IDEs help with that goal.
The library also provides full interoperability with LVGLās C-based APIs and objects. There is memory overhead benchmarking with pprof for analysis and ASan for cross-checks. The design/ directory contains running notes of the approach as the library heads towards a seminal release version. Iām auditing the API coverage and nearly all user-facing APIs (and enums) are covered. I have a few more rounds of contributions planned to improve coverage and reduce redundancy in the implementation.
The two variants of āhello, worldā examples illustrate the improved ergonomics of this API. Besides managing the screen trees, managing more complex interactions with inputs and animations is significantly more modern.
With ESP32 boards as targets of the examples, Iāve naturally been using this library with ESP-IDF. The quantified memory and performance overhead is quite manageable on these boards so far. Should the need arise, thereās an opportunity for an optimization utility where the C++ representation is translated into isomorphic C to eliminate all overhead.
On the topic of maintainability and keeping the C++ implementation up to date: I havenāt tackled an approach to this that is truly automated, and itās unclear to me if any idiomatic C++ API can be distilled to pure bindings (eg., SWIG). Codegen approaches can be leveraged as long as there is backwards compatibility in newer LVGL releases, but for novel LVGL APIs, updating the C++ implementation likely needs maintainer intervention. I intend to add some codegen tools for easily updating this C++ wrapper for new version updates.
Iāve had a look at your wrapper. In many ways the same concept. Iāll give it a try and see how easy it is to convert my modules. I like the fact that you can chain your functions on an object.
I have a few questions:
Why donāt you provide the parent as a reference to your create() functions?
There seems to be a bunch of code written multiple times, like e.g. the width() function. Only difference is the type of the object being returned. I havenāt fully investigated the relations between your different base / core types, but to me it seems like it ought be possible to maybe define those ācommonā functions as templates to avoid having too much copied code to maintain.
I see lvgl is already at version 9.5. Any plans on keeping pace?
Thanks for pointing this out !
You are right, there were many redundant code which was already provided by the ObjectMixin, I removed all of it and everything compiles as usual.
Iāve seen LVGL mention 9.5 on the documentation, but in github releases the last one is the 9.4 release. I have another branch in lv where I prepare modifications for the next release.
For the question about parent as a reference, ObjectView is already a pointer (or behave like one), so same cost of copying, otherwize I will be passing a pointer to a pointer (will be optimized by the compiler but better using the Viewā¦) Itās similar to dealing with std::string_view or std::span
Itās better explained here:
Yeah I see your point. It is just not common C++ style (in my opinion) to regard objects as small copyable parameters, even though it is in this case.
With respect to release 9.5 of LVGL I see that Zephyr-projects main drags in an LVGL version having lv_version.h updated to 9.5. So maybe it is soon to come officially as a release too.
I also miss real constructors so I can do
lv:Box myBox(parent) // parent is any lv object - aka ObjectView
or
lv:checkbox myCheckbox(parent);
At the begining the wrapper was like that, I used to have Button(parent) constructors,
but then I moved into having ::create for clarity meaning that we are creating a new widget and not passing something.
lv::Button btn(parent); is not just pointer assignment, it actually calls lv_btn_create() under the hood and it mutates UI state and does non-trivial runtime work.
LVGL may schedule redraw/layout work right away after create/initial style/flags.
With Box::create(parent), that cost is explicit at the call site.
Actually, I can add the style you want, but I am not very sure I can guarantee I wonāt go into subtile problems difficut to spot and debug.
Donāt know if this is the right place to give feedback. I can do it on github next time if you prefer that.
Iāve tried some hours now to see how to convert a project from lvglpp to your lv CPP implementation.
It is much the same and I do like some of the ideas you have. You have Objects and ObjectViews. Iām not sure I feel it is correct to have Object derive from ObjectView. Seems the wrong way around if you ask me. That said - Iām not sure I ever need to use / define an Object.
Right now the biggest hurdle I look into, is that it seems like I have to declare all LV_USE flags.
Example:
I do not define LV_USE_ARC=1 meaning lv_arch.h ends up being an almost empty file after preprocessing.
In my main.cpp I include <lv/lv.hpp> which I suppose is the intended way to do it.
lv.hpp reads lvgl.h which again reads the almost empty lv_arch.h.
But it also reads lv/core/constants.hpp declaring the kArcMode namespace which fails due to lack of LV_ARC_-defines.
Thought I could just surround kArcMode namespace with #if LV_USE_ARC != 0.
But no - not enough
lv/lv.hpp also includes lv/core/anim.hpp (I donāt enable animation in my procject neither by the way) which implements e.g. exec_arc_rotation() calling lv_arc_set_rotation(). Due to lack of LV_USE_ARC, this function has never been prototyped in my build. So compilation error only fixable by enabling LV_USE_ARC
At first I did like your idea of providing an āincludeā-only implementation, but in practice it is maybe not that good. The problem described above would have been solved by just declaring functions / classes in .h file and then have the implementations in .cpp files.
Also the current implementation needs my compiler to repeat a lot of compilations again and again in all my .cpp files. With separate .cpp files Iād have to build a library just once (still read a lot .h files - I know)
Yeah your #if LV_USE⦠fixed the previous reported issue. Great.
A new problem which might just be my lack of overview: I have a parent to an object and want to get parents size (width, height).
Problem is that get_width(), get _height() and similar functions are found in the ObjectMixin class. Any comments to that?
Also have you considered making vbox and hbox derived from Box. It seems strange they arenāt related
Fixed the first problem by moving most getters and improving the design. Now you will be able to get parents parameters.
For the second question Box and hbox/vbox are the same underlying lv_obj_t.
hbox/vbox just configure it as flex (LV_LAYOUT_FLEX + flow), and in this wrapper also default to size-content.
So itās not āVBox is a Box subclassā, itās the same object with different configuration.
hbox()/vbox() return Flex to expose flex-specific helpers like gap(), justify(), space_between().
Itās possible that we all should collaborate. Iām making progress on porting to LVGL 9.5; I donāt expect it to take long.
Iāve also verified the C++ library with Zephyr via ZMK (which need backwards compatibility with 9.3) as well as ESP32. Thereās also a coverage report that shows nearly all of LVGL is covered well beyond the main widgets (including animations).
Thereās now a published guide on Seeed Studio walking through LVGL C++ on ESP32 S3 as well showing that 30 fps on limited hardware with ThorVG animations (which is compute intensive) is possible with this library.