2026-04-08 12:16 AM
2026-04-08 4:57 AM
Hi Mattias,
thanks for addressing this theme. I did not see any interest from ST in the past and had very low expectations up to now.
My main concern is that CubeMX does not create a C++ main file.
It should be not a big deal to have a check mark somewhere and write/read/change main.cpp instead of main.c.
In case of C++ the generated C funktions for initialization, interrupts, call backs and so on need to be declared extern "C".
Changing HAL or LL functions makes no sense IMO.
For longer editing I change to EMACS anyway, so I'm not particulalry interested in other CubeIDE issues.
(I am much more interested having all tools available on Linux, since Windows is more and more no option for many companies, especially outside USA.)
2026-04-08 5:52 AM - edited 2026-04-08 6:03 AM
try to use "-x c++" with .c files you want to compile as c++.
2026-04-08 6:22 AM - edited 2026-04-08 6:27 AM
I don't mind mixing C and C++. You can always wrap C drivers with a C++ interface. Though it would be nice if there is a native C++ driver interface. The downside is that if there is only a C++ implementation there might be too much overhead or the interface may not be suited for your specific needs. My preference is to have C++ friendly definitions and functions that can easily be wrapped and integrated in C++.
When I use C++ I want to use constexpr as much as possible to do many checks and calculations at compile time instead of run time. Unfortunately constexpr cannot work with pointers, even fixed address pointers. So predefined peripheral addresses such as defined GPIO ports cannot be used unless defined as an integer. I made a topic for this:
https://community.st.com/t5/stm32cubemx-mcus/option-to-not-have-a-gpio-port-typecasted-to-a-pointer/td-p/887164
Another thing that would help is user defined context in HAL callback functions. This way object references can be put in user context allowing static methods to be used as callback functions. There is a topic on this:
https://community.st.com/t5/stm32-mcus-embedded-software/user-defined-context-in-hal-callbacks/m-p/783093
It looks like the feature request on github has been closed and it won't be added to HAL v1. It looks like it is present in HAL V2: https://github.com/STMicroelectronics/STM32CubeU5-V2-Preview/blob/0cf320046f0147a87c5db327c4d7e67e7b75eb27/stm32u5xx_drivers/hal/stm32u5xx_hal_dac.h#L353
Advantage of C++ is function overloading. You can overload functions that use a pointer and a size to a buffer with std::span. Such as transmit functions e.g. HAL_SPI_Transmit().
2026-04-08 7:23 AM
The C++ support is fine as is. Things compile fine, autocomplete works, expressions display correctly. The bigger issues are fixing the annoyances, like a random file opening every time you debug.
2026-04-08 11:33 AM
I think CubeMX not creating a C++ main file is the biggest concern.
I don't think we need "native c++" HAL or LL -- just make sure everything that needs to be extern C is.
-mitch
2026-04-08 11:29 PM - edited 2026-04-08 11:30 PM
Hi Mattias
I have succesfully created my own C++ environment. I generate a C makefile project with CubeMX and then edit the makefile to compile both C and C++ according to it's extension. The challenge was also to go over to C++ 'domain' due to name mangling. But I solved that too. C functions can be called from C++, but the other way around you need to solve the name mangling issue. So I let the CubeMX generated code do all the initialisations etc. Then before the main function hits the while loop, I return and call the C++ main (AppMain) from the startup assembly file. Thereafter it's C++. I developed a few necessary wrappers because now you want the FreeRTOS task to be a class. That was my approach. I hope that helps.
BTW, I code ONLY in VSCode and compile from there and debug from there.
Kind regards
2026-04-09 5:14 AM - edited 2026-04-09 5:26 AM
To all C++ users here: C++ is not a perfect superset of C (unless maybe few very recent versions). So requiring that all ST-provided libraries build perfectly in C++ mode is IMHO not feasible currently. The same applies to the generated initialization code. So please don't skip your C++ lectures and recall the extern "C" thing.
@mattias norlander Maybe you could implement "express C++ mode" in CubeMX, where the project is created with C++ nature from the beginning, and the main file is "main.cpp". Rename the previous main file to c_main.c (or whatever) where main() renamed to c_main(). The new file can look like this:
// generated main.cpp
extern "C" int c_main(void);
// USER CODE here....
[[noreturn]]
auto main() ->int {
// USER CODE here....
(void)c_main();
// USER CODE here....
while(1) {}
// USER CODE here....
}
// USER CODE here....// generated c_main.c
#ifdef __cplusplus
#error
#endif
#include "main.h"
.......
int c_main(void)
{
HAL_Init()...
.......
}
... and proudly call this a feature ;)
2026-04-09 5:30 AM - edited 2026-04-09 5:39 AM
Please can we have the "main" file not called just main.cpp (or main.c) ?
When working with multiple projects, it gets confusing with multiple files all call main !
Better would be <project>.cpp or <project>_main.cpp
Similarly for plain C projects.
2026-04-09 11:26 PM - edited 2026-04-09 11:33 PM
To be able to build a correct C++ Wrapper around the HAL C-Funktions you should extend the Handle-Typedefs with some sort of User Data Pointer like
/**
* @brief UART handle Structure definition
*/
typedef struct __UART_HandleTypeDef
{
void *pUserData; /*!< User Data Pointer */
USART_TypeDef *Instance; /*!< UART registers base address */
UART_InitTypeDef Init; /*!< UART communication parameters */This has been a feature request some time ago, but was declined. See [Feature Request] Pass arbitrary data pointer in callbacks · Issue #23 · STMicroelectronics/STM32CubeG4 and Solved: Feature request: Pass arbitrary data pointer in HA... - STMicroelectronics Community
We can then use the pointer to point back to the C++ Instance in the callbacks like:
#if ((BSP_USE_UART == 1) && defined(HAL_UART_MODULE_ENABLED))
/**
* @brief Tx Transfer completed callbacks.
* @PAram huart Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @attention Overrides HAL_UART_TxCpltCallback from HAL
* @attention Executed in interrupt
*/
extern "C" void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
BspUart* pUart = reinterpret_cast<BspUart*>(huart->pUserData);
if (pUart)
{
pUart->OnTxComplete();
}
}
#endif