Skip to content

Commit 0459596

Browse files
author
Zim Kalinowski
committed
Merge branch 'doc/api_guides_cplusplus' into 'master'
docs: add C++ support chapter to the API guides See merge request espressif/esp-idf!20182
2 parents 8ea3865 + 80d3dc9 commit 0459596

File tree

9 files changed

+181
-18
lines changed

9 files changed

+181
-18
lines changed

docs/en/api-guides/cplusplus.rst

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
C++ Support
2+
===========
3+
4+
.. highlight:: cpp
5+
6+
ESP-IDF is primarily written in C and provides C APIs. However, ESP-IDF supports development of applications in C++. This document covers various topics relevant to C++ development.
7+
8+
The following C++ features are supported:
9+
10+
- :ref:`cplusplus_exceptions`
11+
- :ref:`cplusplus_multithreading`
12+
- :ref:`cplusplus_rtti`
13+
- :doc:`thread-local-storage` (``thread_local`` keyword)
14+
- All C++ features implemented by GCC, except for some :ref:`limitations <cplusplus_limitations>`. See `GCC documentation <https://gcc.gnu.org/projects/cxx-status.html>`_ for details on features implemented by GCC.
15+
16+
esp-idf-cxx Component
17+
---------------------
18+
19+
`esp-idf-cxx <https://github.com/espressif/esp-idf-cxx>`_ component provides higher-level C++ APIs for some of the ESP-IDF features. This component is available from the `IDF Component Registry <https://components.espressif.com/components/espressif/esp-idf-cxx>`_.
20+
21+
.. _cplusplus_multithreading:
22+
23+
C++ language standard
24+
---------------------
25+
26+
By default, ESP-IDF compiles C++ code with C++20 language standard with GNU extensions (``-std=gnu++20``).
27+
28+
To compile the source code of a certain component using a different language standard, set the desired compiler flag in the component CMakeLists.txt file:
29+
30+
.. code-block:: cmake
31+
32+
idf_component_register( ... )
33+
target_compile_options(${COMPONENT_LIB} PRIVATE -std=gnu++2b)
34+
35+
Use ``PUBLIC`` instead of ``PRIVATE`` if the public header files of the component also need to be compiled with the same language standard.
36+
37+
Multithreading
38+
--------------
39+
40+
C++ threads, mutexes, and condition variables are supported. C++ threads are built on top of pthreads, which in turn wrap FreeRTOS tasks.
41+
42+
See :example:`cxx/pthread` for an example of creating threads in C++.
43+
44+
.. _cplusplus_exceptions:
45+
46+
Exception handling
47+
------------------
48+
49+
Support for C++ Exceptions in ESP-IDF is disabled by default, but can be enabled using the :ref:`CONFIG_COMPILER_CXX_EXCEPTIONS` option.
50+
51+
If an exception is thrown, but there is no ``catch`` block, the program will be terminated by the ``abort`` function, and the backtrace will be printed. See :doc:`Fatal Errors <fatal-errors>` for more information about backtraces.
52+
53+
C++ Exceptions should *only* be used for exceptional cases, something happening unexpectedly and that is quite rare, e.g. an event that happens less frequently than 1 every 100 times. *Do not* use them for control flow (see also the section about resource usage below)! For more information on how to use C++ Exceptions, see the `ISO C++ FAQ <https://isocpp.org/wiki/faq/exceptions>`_ and `CPP Core Guidelines <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-errors>`_.
54+
55+
See :example:`cxx/exceptions` for an example of C++ exception handling.
56+
57+
C++ Exception Handling and Resource Usage
58+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
59+
60+
Enabling exception handling normally increases application binary size by a few KB.
61+
62+
Additionally, it may be necessary to reserve some amount of RAM for exception emergency pool. Memory from this pool will be used if it is not possible to allocate exception object from the heap. The amount of memory in the emergency pool can be set using the :ref:`CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE` variable. Some additional stack memory (around 200 bytes) will also be used if and only if a C++ Exception is actually thrown, because it requires calling some functions from the top of the stack to initiate exception handling.
63+
64+
The run time of code using C++ exceptions depends on what actually happens at run time. If no exception is thrown, the code tends to be somewhat faster since there is no need to check error codes. If an exception is thrown, the run time of the code that handles exceptions will be orders of magnitude slower than code returning an error code. This increase may or may not be significant, however, in the entire application, in particular if the error handling requires additional action, such as a user input or messaging to a cloud. But exception-throwing code should never be used in real-time critical code paths.
65+
66+
.. _cplusplus_rtti:
67+
68+
Runtime Type Information (RTTI)
69+
-------------------------------
70+
71+
Support for RTTI is disabled by default, but can be enabled using :ref:`CONFIG_COMPILER_CXX_RTTI` option.
72+
73+
Enabling this option compiles all C++ files with RTTI support enabled, which allows using ``dynamic_cast`` conversion and ``typeid`` operator. Enabling this option typically increases the binary size by tens of kB.
74+
75+
See :example:`cxx/rtti` for an example of using RTTI in ESP-IDF.
76+
77+
78+
Developing in C++
79+
-----------------
80+
81+
The following sections provide tips on developing ESP-IDF applications in C++.
82+
83+
Combining C and C++ code
84+
^^^^^^^^^^^^^^^^^^^^^^^^
85+
86+
When part of the application is developed in C and part in C++, it is important to understand the concept of `language linkage <https://en.cppreference.com/w/cpp/language/language_linkage>`_.
87+
88+
In order for a C++ function to be callable from C code, it has to be both *declared* and *defined* with C linkage (``extern "C"``)::
89+
90+
// declaration in the header file:
91+
#ifdef __cplusplus
92+
extern "C" {
93+
#endif
94+
95+
void my_cpp_func(void);
96+
97+
#ifdef __cplusplus
98+
}
99+
#endif
100+
101+
// definition in a .cpp file:
102+
extern "C" void my_cpp_func(void) {
103+
// ...
104+
}
105+
106+
107+
In order for a C function to be callable from C++, it has to be *declared* with C linkage::
108+
109+
// declaration in the header file:
110+
#ifdef __cplusplus
111+
extern "C" {
112+
#endif
113+
114+
void my_c_func(void);
115+
116+
#ifdef __cplusplus
117+
}
118+
#endif
119+
120+
// definition in a .c file:
121+
void my_c_func(void) {
122+
// ...
123+
}
124+
125+
126+
Defining ``app_main`` in C++
127+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
128+
129+
ESP-IDF expects the application entry point, ``app_main``, to be defined with C linkage. When ``app_main`` is defined in a .cpp source file, it has to be designated as ``extern "C"``::
130+
131+
extern "C" void app_main()
132+
{
133+
}
134+
135+
136+
Designated initializers
137+
^^^^^^^^^^^^^^^^^^^^^^^
138+
139+
Many of the ESP-IDF components use :ref:`configuration structures <api_reference_config_structures>` as arguments to the initialization functions. ESP-IDF examples written in C routinely use `designated initializers <https://en.cppreference.com/w/c/language/struct_initialization>`_ to fill these structures in a readable and a maintainable way.
140+
141+
C and C++ languages have different rules with regards to the designated initializers. For example, C++ language version C++20, currently the default in ESP-IDF, does not support out-of-order designated initialization, nested designated initialization, mixing of designated initializers and regular initializers, and designated initialization of arrays. Therefore, when porting ESP-IDF C examples to C++, some changes to the structure initializers may be necessary. See the `C++ aggregate initialization reference <https://en.cppreference.com/w/cpp/language/aggregate_initialization>`_ for more details.
142+
143+
144+
iostream
145+
^^^^^^^^
146+
147+
``iostream`` functionality is supported in ESP-IDF, with a couple of caveats:
148+
149+
1. Normally ESP-IDF build process eliminates the unused code. However in the case of iostreams, simply including ``<iostream>`` header in one of the source files significantly increases the binary size (by about 200 kB).
150+
2. By default, ESP-IDF uses a simple non-blocking implementation of the standard input stream (``stdin``). To get the usual behavior of ``std::cin``, the application has to initialize the UART driver and enable the blocking mode as shown in :example_file:`common_components/protocol_examples_common/stdin_out.c`.
151+
152+
.. _cplusplus_limitations:
153+
154+
Limitations
155+
-----------
156+
157+
- Linker script generator doesn't support function level placements for functions with C++ linkage.
158+
- Various section attributes (such as ``IRAM_ATTR``) are ignored when used with template functions.
159+
- Vtables are placed into Flash and are not accessible when the flash cache is disabled. Therefore, virtual function calls should be avoided in :ref:`IRAM-safe interrupt handlers <iram-safe-interrupt-handlers>`. Placement of Vtables cannot be adjusted using the linker script generator, yet.
160+
- C++ filesystem (``std::filesystem``) features are not supported.
161+
162+
What to Avoid
163+
-------------
164+
165+
Do not use ``setjmp``/``longjmp`` in C++! ``longjmp`` blindly jumps up the stack without calling any destructors, easily introducing undefined behavior and memory leaks. Use C++ exceptions instead, they will guarantee correctly calling destructors. If you cannot use C++ exceptions, use alternatives (except ``setjmp``/``longjmp`` themselves) such as simple return codes.

docs/en/api-guides/error-handling.rst

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,4 @@ Error handling patterns
186186
C++ Exceptions
187187
--------------
188188

189-
Support for C++ Exceptions in ESP-IDF is disabled by default, but can be enabled using :ref:`CONFIG_COMPILER_CXX_EXCEPTIONS` option.
190-
191-
Enabling exception handling normally increases application binary size by a few KB. Additionally it may be necessary to reserve some amount of RAM for exception emergency pool. Memory from this pool will be used if it is not possible to allocate exception object from the heap. Amount of memory in the emergency pool can be set using :ref:`CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE` variable.
192-
193-
If an exception is thrown, but there is no ``catch`` block, the program will be terminated by ``abort`` function, and backtrace will be printed. See :doc:`Fatal Errors <fatal-errors>` for more information about backtraces.
194-
195-
See :example:`cxx/exceptions` for an example of C++ exception handling.
189+
See :ref:`cplusplus_exceptions`.

docs/en/api-guides/index.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,17 @@ API Guides
1010
:SOC_BT_SUPPORTED: blufi
1111
bootloader
1212
build-system
13+
:SOC_SUPPORT_COEXISTENCE: coexist
1314
core_dump
15+
cplusplus
1416
:SOC_RTC_MEM_SUPPORTED: deep-sleep-stub
1517
:SOC_USB_OTG_SUPPORTED: dfu
1618
error-handling
1719
:SOC_BLE_MESH_SUPPORTED: esp-ble-mesh/ble-mesh-index
1820
freertos-smp
1921
:SOC_WIFI_MESH_SUPPORT: esp-wifi-mesh
2022
event-handling
23+
:SOC_SPIRAM_SUPPORTED: external-ram
2124
fatal-errors
2225
../security/flash-encryption
2326
:esp32s3: flash_psram_config
@@ -30,10 +33,10 @@ API Guides
3033
openthread
3134
partition-tables
3235
performance/index
36+
reproducible-builds
3337
:not esp32c6: RF_calibration
3438
:esp32: ../security/secure-boot-v1
3539
../security/secure-boot-v2
36-
:SOC_SPIRAM_SUPPORTED: external-ram
3740
thread-local-storage
3841
tools/index
3942
unit-tests
@@ -42,5 +45,3 @@ API Guides
4245
:SOC_USB_SERIAL_JTAG_SUPPORTED: usb-serial-jtag-console
4346
:SOC_WIFI_SUPPORTED: wifi
4447
:SOC_WIFI_SUPPORTED: wifi-security
45-
:SOC_SUPPORT_COEXISTENCE: coexist
46-
reproducible-builds

docs/en/libraries-and-frameworks/libs-frameworks.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,7 @@ ESP-BSP
101101

102102
`ESP-BSP <https://github.com/espressif/esp-bsp>`_ repository contains Board Support Packages (BSPs) for various Espressif's and 3rd party development boards. BSPs are useful for quick start on a supported board. Usually they contain pinout definition and helper functions, that will initialize peripherals for the specific board. Additionally, the BSP would contain drivers for external chips populated on the development board, such as sensors, displays, audio codecs etc.
103103

104+
ESP-IDF-CXX
105+
-----------
104106

107+
`ESP-IDF-CXX <https://github.com/espressif/esp-idf-cxx>`_ contains C++ wrappers for part of ESP-IDF. The focus is on ease of use, safety, automatic resource management and shifting checks to compile time instead of failing at run time. There are C++ classes for ESP-Timer, I2C, SPI, GPIO and other peripherals or features of ESP-IDF. ESP-IDF-CXX is `available as a component <https://components.espressif.com/components/espressif/esp-idf-cxx>`_ from the component registry. Please check the project's `README.md <https://github.com/espressif/esp-idf-cxx/blob/main/README.md>`_ for more information.

docs/zh_CN/api-guides/cplusplus.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.. include:: ../../en/api-guides/cplusplus.rst

docs/zh_CN/api-guides/error-handling.rst

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,4 @@ ESP-IDF 中大多数函数会返回 :cpp:type:`esp_err_t` 类型的错误码,
186186
C++ 异常
187187
--------
188188

189-
默认情况下,ESP-IDF 会禁用对 C++ 异常的支持,但是可以通过 :ref:`CONFIG_COMPILER_CXX_EXCEPTIONS` 选项启用。
190-
191-
通常情况下,启用异常处理会让应用程序的二进制文件增加几 KB。此外,启用该功能时还应为异常事故池预留一定内存。当应用程序无法从堆中分配异常对象时,就可以使用这个池中的内存。该内存池的大小可以通过 :ref:`CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE` 来设定。
192-
193-
如果 C++ 程序抛出了异常,但是程序中并没有 ``catch`` 代码块来捕获该异常,那么程序的运行就会被 ``abort`` 函数中止,然后打印回溯信息。有关回溯的更多信息,请参阅 :doc:`不可恢复错误 <fatal-errors>` 。
194-
195-
C++ 异常处理示例,请参考 :example:`cxx/exceptions`。
189+
请参考 :ref:`cplusplus_exceptions`。

docs/zh_CN/api-guides/index.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,5 @@ API 指南
4343
:SOC_WIFI_SUPPORTED: wifi
4444
:SOC_WIFI_SUPPORTED: wifi-security
4545
:SOC_SUPPORT_COEXISTENCE: coexist
46-
reproducible-builds
46+
reproducible-builds
47+
cplusplus

examples/cxx/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# C++ Example Applications
2+
3+
The example applications here show that basic C++ features work in ESP-IDF. If you are looking for high-level C++ APIs, please take a look at [ESP-IDF-CXX](https://github.com/espressif/esp-idf-cxx). It has a range of C++ wrapper classes which aim to be easy-to-use, safe, provide automatic resource management and check more at compile time to avoid run time errors.

tools/cmake/build.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ function(__build_set_lang_version)
126126
if(NOT IDF_TARGET STREQUAL "linux")
127127
# Building for chip targets: we use a known version of the toolchain.
128128
# Use latest supported versions.
129+
# Please update docs/en/api-guides/cplusplus.rst when changing this.
129130
set(c_std gnu17)
130131
set(cxx_std gnu++20)
131132
else()

0 commit comments

Comments
 (0)