In embedded development, we often encounter a situation where: the underlying driver library is written in C language (<span><span>.c</span></span> file), while the upper application or framework is in C++ (<span><span>.cpp</span></span> file). As a result, when we call it, we get:
undefined reference to `xxx_function'
Clearly, it is declared in the <span><span>.h</span></span> file and implemented in the <span><span>.c</span></span> file, and there are no compilation errors, so why does the linker fail?
1. Root Cause: Different Name Mangling Between C and C++
-
The C compiler generates function symbols as they are, for example:
foo -
The C++ compiler performs name mangling, encoding the function name and parameter types, for example:
_Z3fooi
Therefore, when C++ calls functions written in C, if the name mangling is not handled, the linker cannot find the implementation.
2. Solution: Use <span><span>extern "C"</span></span>
Simply inform the C++ compiler that “these functions are exported in C style,” and it will match up.
✅ Method 1: Wrap in Header File (Recommended)
#ifdef __cplusplusextern "C" {#endif
void foo(int x);int bar(const char* str);
#ifdef __cplusplus}#endif
This way, whether included in <span><span>.c</span></span> or <span><span>.cpp</span></span>, the symbol names will remain consistent.
✅ Method 2: Explicit Declaration in C++ File
extern "C" void foo (int x);extern "C" int bar(const char* str);
3. Common Misconceptions
-
“Just declare it again”: Not adding
<span><span>extern "C"</span></span>is useless; the symbol name is still mangled. -
“Change .c to .cpp”: This will lead to a bunch of C library compilation errors, not recommended.
-
“Is it not compiled into the project?”: Sometimes it is indeed the source file that is not included, but if the function implementation is indeed in the
<span><span>.c</span></span>file, most of these undefined references are due to inconsistent linking conventions.
4. Summary
In short:
When C++ calls C library functions, remember to add
<span><span>extern "C"</span></span>!
This is basic knowledge for mixed C/C++ projects and a common pitfall for many beginners.
📌 Example Scenarios
-
In STM32 projects, HAL/drivers are written in C, and when TouchGFX or C++ applications call them,
<span><span>extern "C"</span></span>is needed. -
In cross-platform projects, when porting C libraries to C++ projects, the same attention is required.
🔑 Remember this principle: Whenever C++ calls C, always check if <span><span>extern "C"</span></span> is wrapped in the header file.
This way, you can eliminate a large portion of “undefined reference” errors.