Description
All use C, and the storage occupied by global variables used by the business is too large,So I want to take CPP to complete it.
When C99 is checked, many errors are prompted when compiling the cpp file. After canceling C99, compiling lv_color.h file prompts many errors.
How to be compatible with C++ on the STM32 platform?
What MCU/Processor/Board and compiler are you using?
STM32F429,ARM Compiler V5
What LVGL version are you using?
V7.3.0
What do you want to achieve?
Using arm compiler V5, I can compile littlevgl and C++.
What have you tried so far?
Code to reproduce
Screenshot and/or video
If possible, add screenshots and/or videos about the current state.
Compile LVGL as C code and the rest of your code as C++. We don’t support compiling LVGL files as C++, but including its headers in a C++ file should work without problems.
Please make sure you are using the latest version of LVGL from release/v7
or master
- there have been fixes for C++ builds in the recent past.
I just tried it with lvgl V7.5.0, in the CPP file #include “lvgl.h”, some errors will be reported
The lvgl.h in lvgl-master folder.
In this CPP file, I only used the method in lv_mem.h
Change to include “src/lv_misc/lv_mem.h” and there is no problem.
But in the place where the widget is displayed, I cannot avoid this problem
Looking like you use an old version of c++ standard, try to change ARM Compiler version to 6 on page “Target” and language for C++ on page “C/C++ (AC)” to c++11 or newer
Also, I’ll make my macro _LV_COLOR_MAKE_TYPE_HELPER more compatible with Keil c++98 compiler. But to fix other errors you need change ARM Compiler version from 5 to 6
Thanks~
In order to be compatible with C++98, I also modified LV_COLOR_MAKE.The code I modified is not very good
Upgrade to v6, some compilation instructions also need to be changed…And I am also worried that the file compiled by v6 is larger than V5.
By the way, how do you set the event callback function elegantly in CPP?
Like this?
class CWnd
{
public:
static void CWnd_defEventCB(lv_obj_t * obj, lv_event_t e);
};
You can check my pull request https://github.com/lvgl/lvgl/pull/1788
There fixed compilation with ARM Compiler version 6.
About callbacks, for example usage of lv_task_create:
C++ 98 way:
class SomeClass
{
public:
void someFunction()
{
lv_task_create(&SomeClass::taskCallback, 500, LV_TASK_PRIO_MID, this);
}
private:
void makeSomething()
{
printf("something");
}
static void taskCallback(lv_task_t* task)
{
SomeClass* self = reinterpret_cast<SomeClass*>(task->user_data);
self->makeSomething();
}
};
C++11 way using lambda:
class SomeClassCpp11
{
public:
void someFunction()
{
lv_task_create([](auto task)
{
auto self = reinterpret_cast<SomeClassCpp11*>(task->user_data);
self->makeSomething();
}, 500, LV_TASK_PRIO_MID, this);
}
private:
void makeSomething()
{
printf("something");
}
};
Thanks for your reply.Got it!
1.Class’s static member function~
2.pass “this” to “user data” when creating the task…
But the event call back of the control(eg:button) is a bit different.
Event callback for the control is similar:
class ButtonWrapper
{
public:
ButtonWrapper()
{
button_ = lv_btn_create(lv_scr_act(), NULL);
lv_obj_set_event_cb(button_, &ButtonWrapper::buttonCallback);
lv_obj_set_user_data(button_, this);
}
~ButtonWrapper()
{
lv_obj_del(button_);
}
private:
void eventHandler(lv_event_t event)
{
switch(event)
{
case LV_EVENT_PRESSED:
printf("ButtonWrapper pressed\n");
break;
}
}
static void buttonCallback(lv_obj_t* obj, lv_event_t event)
{
ButtonWrapper* self = reinterpret_cast<ButtonWrapper*>(lv_obj_get_user_data(obj));
self->eventHandler(event);
}
private:
lv_obj_t* button_;
};
1 Like
Hi! I am using LVGL
version 8.3.1
and after my “adapting” the code, I get an error:
argument of type "void(*)(lv_obj_t *obj, lv_event_t *event)" incompatible with the "lv_event_cb_t" type parameter
class ButtonWrapper
{
public:
ButtonWrapper()
{
button_ = lv_btn_create(lv_scr_act());
lv_obj_add_event_cb(button_, &ButtonWrapper::buttonCallback, LV_EVENT_VALUE_CHANGED, NULL); // <----------- The error is here
lv_obj_set_user_data(button_, this);
}
~ButtonWrapper()
{
lv_obj_del(button_);
}
private:
void eventHandler(lv_event_t *e)
{
lv_event_code_t code = lv_event_get_code(e);
switch (code)
{
case LV_EVENT_PRESSED:
printf("ButtonWrapper pressed\n");
break;
}
}
static void buttonCallback(lv_obj_t *obj, lv_event_t *event)
{
ButtonWrapper *self = reinterpret_cast<ButtonWrapper *>(lv_obj_get_user_data(obj));
self->eventHandler(event);
}
private:
lv_obj_t *button_;
};
Please help to adapt the code.
1st:
class ButtonWrapper
{
public:
ButtonWrapper()
{
button_ = lv_btn_create(lv_scr_act());
lv_obj_add_event_cb(button_, &ButtonWrapper::buttonCallback, LV_EVENT_VALUE_CHANGED, NULL);
lv_obj_set_user_data(button_, this);
}
~ButtonWrapper()
{
lv_obj_del(button_);
}
private:
void eventHandler(lv_event_t* e)
{
lv_event_code_t code = lv_event_get_code(e);
switch (code)
{
case LV_EVENT_PRESSED:
printf("ButtonWrapper pressed\n");
break;
}
}
static void buttonCallback(lv_event_t* e)
{
lv_obj_t* obj = lv_event_get_target(e);
ButtonWrapper* self = reinterpret_cast<ButtonWrapper*>(lv_obj_get_user_data(obj));
self->eventHandler(e);
}
private:
lv_obj_t* button_;
};
2nd:
class ButtonWrapper
{
public:
ButtonWrapper()
{
button_ = lv_btn_create(lv_scr_act());
lv_obj_add_event_cb(button_, &ButtonWrapper::buttonCallback, LV_EVENT_VALUE_CHANGED, this);
}
~ButtonWrapper()
{
lv_obj_del(button_);
}
private:
static void eventHandler(lv_event_t* e)
{
lv_event_code_t code = lv_event_get_code(e);
switch (code)
{
case LV_EVENT_PRESSED:
printf("ButtonWrapper pressed\n");
break;
}
}
static void buttonCallback(lv_event_t* e)
{
ButtonWrapper* self = reinterpret_cast<ButtonWrapper*>(lv_event_get_user_data(e));
self->eventHandler(e);
}
private:
lv_obj_t* button_;
};