Using the Exported C Code

Overview

When C code is exported from LVGL's UI Editor, no XML is needed at all (LV_USE_XML can be 0), and it's very similar to the case when the C code is written by hand.

The exported C code can simply be dropped into the project and compiled into the application.

Initialization

The main entry point is ui_init("asset_path") located in ui.c.

Its only parameter is a path where the file-based assets (fonts and images) are located. For example, if a PNG and TTF file are located at "A:my_ui/v2.3/assets", it should be passed to ui_init() so all the used paths can be prefixed. That is, if images/logo.png was used in the UI Editor, then the full path will be "A:my_ui/v2.3/assets/images/logo.png".

Note that ui_init() creates only the permanent screens but doesn't load any screens. However, this can be done easily by calling lv_screen_load(screen1).

Screens can also be created easily by calling their generated create function, e.g. main_screen_create().

Structure of the Exported Code

Code export follows some conventions.

The generated files end with _gen.c or _gen.h. These shouldn't be modified as they will be overwritten on the next code generation.

For the non-generated files, only a skeleton is generated once (if the file doesn't exist). Here, the user can add custom code as needed.

From the XMLs of screens and components, "create" functions are generated using the name of the file. For example:

  • lv_obj_t * main_screen_create(void) from main_screen.xml

  • lv_obj_t * my_button_create(lv_obj_t * parent, const char * button_text) from my_button.xml

For Components, no setters are created, but all the parameters are passed to the create function.

From each globals.xml, four files are created:

  • Generated C and H files containing all subject, font, image, style, and other initializations.

  • Non-generated C and H files that are just wrappers around the generated ones where custom code can be placed.

The name of these files is the name of the folder containing the globals.xml file by default. It can be overridden by <globals name="my_lib">.

Adding Custom Code

In some cases, it might be necessary to extend the generated code with hand-written code. Let's see how it can be done in different cases.

Adding Generic Code

lv_timer, a subject with a special observer, complex animations, or styles can be added in ui.c or the C file created from globals.xml.

For example, to add some style properties to an XML-defined style:

void ui_init(const char * asset_path)
{
    LV_LOG_USER("ui_init()\n");
    ui_lib_init(asset_path);

    lv_style_set_bg_color(&style_1, get_special_color());
}

To create a special subject which formats an integer temperature value as a string with a decimal point:

/* Assume that subject_temperature_int stores the value with 0.1 degree resolution */
/* E.g. 345 means 34.5 */

void temperature_to_string_observer_cb(lv_observer_t * observer,
                                       lv_subject_t * subject)
{
    int32_t upscaled_value = lv_subject_get_int(&subject_temperature_int);

    int32_t int_part = upscaled_value / 10;
    int32_t fract_part = upscaled_value % 10;

    char buf[64];
    lv_snprintf(buf, sizeof(buf), "%d.%d", int_part, fract_part);
    lv_subject_copy_string(&subject_temperature_string, buf);
}

lv_subject_add_observer(&subject_temperature_int,
                        temperature_to_string_observer_cb, NULL);

Component wrapper

If a component needs to be extended with a feature or API that is not supported by the editor, the simplest solution is to create a wrapper component.

For example, let's say my_button.xml describes some feature of a button, but some setters, special APIs, or extra features need to be added. In this case, just manually create new C and H files for a super_button with a function like:

lv_obj_t * super_button_create(lv_obj_t * parent, ...some_arguments...)
{
    lv_obj_t * my_button = my_button_create(parent, ...);

    /* ...do something with the created `my_button` */

    return my_button;
}

CMake Integration

A skeleton CMakeLists.txt file is generated which can be easily integrated into any project.

A file called file_list_gen.cmake is generated and used by CMakeLists.txt. It ensures that only the appropriate files are included.