lv_binding_cpp icon indicating copy to clipboard operation
lv_binding_cpp copied to clipboard

Still on ?

Open AlixANNERAUD opened this issue 1 year ago • 11 comments

Hello, Is this project still on? I would be interested in doing the binding.

AlixANNERAUD avatar Jun 08 '23 18:06 AlixANNERAUD

I am also interested in doing a C++ binding. After a quick review of this project, I believe it could be done in a more "Standard" compliant manner than this.

RobinPurtee avatar Jul 05 '23 19:07 RobinPurtee

Hi guys,

Thank you for writing. Sorry @AlixANNERAUD somehow I haven't noticed your comment earlier. :slightly_frowning_face:

This project is really stale now, but it would be really great to have a C++ binding!

My 400 USD offering in the README is still also active.

However there is one more thing: LVGL v9 will be released by end of this year so we should target the v9 API with the C++ binding too. There will be some refactoring later on on the API but no conceptual changes.

kisvegabor avatar Jul 06 '23 17:07 kisvegabor

Hello, OK, well I'm working on it. However, could you tell me what a typical widget class should look like? Because at the moment I'm using an approach where the class just contains a pointer to the widget which is then used/modified by the various methods. I'm not sure this is exactly what you're thinking...

AlixANNERAUD avatar Jul 16 '23 17:07 AlixANNERAUD

How can it be used? E.g. how the set the size and position of a button and how to add an event to it?

kisvegabor avatar Jul 17 '23 14:07 kisvegabor

Alix, I have been reviewing this code. To answer your question: A class containing a pointer to a widget and using that to invoke the C functions is exactly what you want. Basically. What you really want is a class that encapsulates an 'lv_obj_t*' and the widget classes derive from that, as it is in this code base. The basic design of this code base is correct. The issues I have are with the implementation. Chief among them being it is designed to be fluent (i.e. methods return a reference to the object). While fluent design is cool, but it makes the code difficult to in-line without adding bytes. The ideal C++ binding should not add any amount of code storage above what a C implementation would. While that may not be completely possible, placing function return value on what is effectively a void method is difficult to optimize away. Also the coding style used, while not uncommon, is not the same has the C code base, nor current C++ standard library, style. Using the same naming convention has the C library would make it easier for developers to move from C to C++. It should that they use the library basically the same way did before, but do not have to worry about object life time management has much.

RobinPurtee avatar Jul 18 '23 00:07 RobinPurtee

Hello, I've started generating the binding from scratch again using PyGCCXML. Here is the wrapper class for lv_obj_t as an example (don't pay attention to the casing ^^ ) :

namespace LVGL
{
    typedef class Object_Class
	{
    public:
		virtual ~Object_Class();
		void Clean();
		void Del_Delayed(uint32_t delay_ms);
		void Del_Anim_Ready_Cb(lv_anim_t * a);
		void Del_Async();
		void Set_Parent(Object_Class parent);
		/* ... */
		void Move_Background();
		uint32_t Get_Child_Id();
		inline Object_Class(lv_obj_t* LVGL_Pointer) : LVGL_Pointer(LVGL_Pointer) { };
		inline Object_Class() : LVGL_Pointer(NULL) { };
		inline lv_obj_t* Get_LVGL_Pointer() const { return LVGL_Pointer; };_lv_obj_t* Object_Class::Get_Child(int32_t id)
{
	return lv_obj_get_child(LVGL_Pointer, id);
}
		inline void Clear_Pointer() { LVGL_Pointer = NULL; };

		static const lv_obj_class_t& Class;
	protected:
		lv_obj_t* LVGL_Pointer;
    } Object_Type;
}

Some function here are not part of LVGL, it's only for shorter implementation.

And here the definition of one function as an example :

Object_Type Object_Class::Get_Child(int32_t id)
{
	return Object_Type(lv_obj_get_child(LVGL_Pointer, id));
}

Does this look right to you ? I'd like to use a more RAII-oriented model (object creation / deletion) within the constructor, move semantic ...), but I don't think it's the most suitable for this context.

AlixANNERAUD avatar Aug 12 '23 10:08 AlixANNERAUD

Hello, I have a first working version that generates a binding for almost all the wigets (the rest will come later). It is RAII oriented (all the objects are deleted out of the scope):

 LVGL::Object_Type Screen(lv_scr_act());

  LVGL::Button_Type B(Screen);
  B.Set_Align(LV_ALIGN_CENTER);

  LVGL::Label_Type Label(B);

  LVGL::Switch_Type S(Screen);
  S.Set_Align(LV_ALIGN_BOTTOM_LEFT);
  
  LVGL::Colorwheel_Type C(Screen, true);
  C.Set_Align(LV_ALIGN_BOTTOM_RIGHT);
  C.Set_Size(200, 200);

  Label.Set_Text("Hello World!");

Would it be possible to have your opinion on it? If you want to test it, I suggest you use my development environment available here: https://github.com/AlixANNERAUD/LVGL-Cpp-Binding-Environment (a fork of the native LVGL platform io). Just run Main.my inside the Tool folder, it's will generate the binding inside the LVGL_Cpp folder. Juste include from it the LVGL_Cpp.hpp file and you are done. Bye.

AlixANNERAUD avatar Aug 23 '23 18:08 AlixANNERAUD

Thank you for the update. Does this code just creates a an obj on the current screen, right? So I wonder why the variable is called "Screen"?

Shouldn't it be LVGL::Object_Type Screen(NULL);?

kisvegabor avatar Aug 25 '23 19:08 kisvegabor

Hello, Sorry for my late reply, I've just come back from vacation. The first object instantiated Screen is instantiated from a pointer : there is a normal constructor that actually create an object and a constructor from a LVGL pointer which juste copy the LVGL pointer (no object creation). I know this can be confusing, but it simplifies the generation of binding code greatly.

Here's what the two constructors code looks like, roughly speaking :

Object_Class::Object_Class(lv_obj_t* LVGL_Pointer) : LVGL_Pointer(LVGL_Pointer)
{
}

Object_Class::Object_Class(Object_Class& Parent_Object) : LVGL_Pointer(NULL) // ! : This is not a copy constructor !!
{
this->LVGL_Pointer = lv_obj_create(Parent_Object.LVGL_Pointer)
}

I don't think LVGL::Object_Type Screen(NULL) is right, because then only the child object of Screen would be a screen actually, which isn't the point here. Rest assured, this isn't the final design at all, just some quick code for testing purposes.

AlixANNERAUD avatar Aug 31 '23 09:08 AlixANNERAUD

In LVGL v9 I'm thinking about having an lv_obj_t * lv_screen_create(void) function and remove the "create screen with NULL parent". Would it help for the binding?

kisvegabor avatar Aug 31 '23 22:08 kisvegabor

Well, it's could help, and would make more sense, but it's not required.

AlixANNERAUD avatar Sep 04 '23 18:09 AlixANNERAUD