Lvgl custom external malloc implementation / linking

Baldhead
Posts: 515
Joined: Sun Mar 31, 2019 5:16 am
Location: Brazil

Lvgl custom external malloc implementation / linking

Postby Baldhead » Thu Mar 19, 2026 1:24 am

Hi,

What do you want to achieve ?
I want to create custom functions for Lvgl memory allocator and that compilation and linking work.

What have you tried so far ?
I downloaded Lvgl from “ESP Component Registry”.

In esp-idf menuconfig, inside Lvgl component config , i select the option “implement the function externally” in “Malloc functions source”.

I created the malloc families functions inside my components folder in my project folder.
C:\esp32-Proj\proj\components\lv_mem_custom_alloc\src\include\lv_mem_custom_alloc.h
C:\esp32-Proj\proj\components\lv_mem_custom_alloc\src\lv_mem_custom_alloc.c
C:\esp32-Proj\proj\components\lv_mem_custom_alloc\CMakeLists.txt

Lvgl folder stay located in managed_components folder inside my project folder.
C:\esp32-Proj\proj\managed_components\lvgl__lvgl

I tried using inline functions too in a .h file, but no luck.

When compiling project, at linker stage, the linker show undefined reference to.

Doubts
How do I get lvgl to recognize(link) my components folder (subfolder inside components folder) ?
C:\esp32-Proj\proj\components\lv_mem_custom_alloc

What are all the functions that need to be defined, which ones are mandatory, and how do I define / write mem_init() if needed ?
There’s a memory_init() function that I’m not sure it is necessary. I think only malloc(), realloc() and free() would be needed, but it seems I need to define other functions as well.

Is there any documentation on how to do this ?

Code to reproduce
lv_mem_custom_alloc.h file:

Code: Select all

void* lv_malloc_core(size_t size);
void* lv_realloc_core(void* ptr, size_t size);
void lv_free_core(void* ptr);
lv_mem_custom_alloc.c file:

Code: Select all

void* lv_malloc_core(size_t size)
{
    return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT, MALLOC_CAP_SPIRAM);
}

void* lv_realloc_core(void* ptr, size_t size)
{
    return heap_caps_realloc_prefer(ptr, size, 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT, MALLOC_CAP_SPIRAM);
}

void lv_free_core(void* ptr)
{
    heap_caps_free(ptr);
}
Environment
ESP32-S3
ESP-IDF 5.5.3 with visual studio code
LVGL 9.4.0
Custom board.

Notes:
* The project is running (without custom memory allocator), but sometimes, i think, that “normal” allocator cannot allocate memory, and the system crash or the task running lvgl crash.
* https://forum.lvgl.io/t/how-to-implemen ... -idf/23723
Last edited by Baldhead on Thu Mar 19, 2026 10:47 pm, edited 2 times in total.

Baldhead
Posts: 515
Joined: Sun Mar 31, 2019 5:16 am
Location: Brazil

Re: Lvgl custom external malloc implementation / linking

Postby Baldhead » Thu Mar 19, 2026 10:36 pm

Some suggestion ?

MicroController
Posts: 2661
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Lvgl custom external malloc implementation / linking

Postby MicroController » Thu Mar 19, 2026 11:34 pm

How do I get lvgl to recognize(link) my components folder (subfolder inside components folder) ?
Function implementations to link need (only) be available at link time of the application. So if any part of your application declares some dependency to your implementations, i.e. REQUIRES lv_mem_custom_alloc,, they should be built and available at link time.

Not sure about how to 'cleanly' make lvgl include your functions' declarations without touching the managed_components though.

Baldhead
Posts: 515
Joined: Sun Mar 31, 2019 5:16 am
Location: Brazil

Re: Lvgl custom external malloc implementation / linking

Postby Baldhead » Fri Mar 20, 2026 1:53 am

It seems that this solved it (It compiled and linked, but I haven't tested it on the hardware yet).

Necessary functions (only .c file, the function interface(.h file), the lvgl library already provides):
lv_malloc_core()
lv_realloc_core()
lv_free_core()
lv_mem_init()

Optional functions (only .c file, the function interface(.h file), the lvgl library already provides):
lv_mem_monitor_core() // I left a comment in my source code.
lv_mem_test_core() // I left a comment in my source code.


Note:
lv_mem_init() only needs to be declared empty for compilation, since heap initialization is provided by esp-idf.

I don't know if all the steps below are necessary, but this is how it worked.

1. In your component's CMakeLists.txt file (the one containing the memory functions), add:
2. Define Visibility as INTERFACE
If your component provides the functions that LVGL uses, it needs to export those definitions. In your component's CMakeLists.txt file under components:

idf_component_register(
SRCS "your_memory.c"
INCLUDE_DIRS "include"
# Forces the linker to include all the functions of this component.
# even if no one explicitly calls them in the main
WHOLE_ARCHIVE // I only added this to my idf_component_register because the rest I already had.
)

# This tells CMake: "Whoever uses me (or whoever the system links to)
# It needs to be linked to my memory functions.
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u lv_malloc_core")
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u lv_realloc_core")
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u lv_free_core")

#target_link_libraries(${COMPONENT_LIB} INTERFACE "-u lv_mem_monitor_core") // comment out
#target_link_libraries(${COMPONENT_LIB} INTERFACE "-u lv_mem_test_core") // comment out


3. Linking Order
ESP-IDF links components in the order they appear. If LVGL requests malloc_custom and your component hasn't yet been "seen" by the linker, it will throw an error.
Add the following to the CMakeLists.txt file at the project root.

# It forces the linker to process its memory component before LVGL.
idf_build_set_property(LINK_COMPONENTS "lv_mem_custom_alloc" APPEND)

Who is online

Users browsing this forum: Bing [Bot], Semrush [Bot] and 16 guests