Why Does Calling C Functions from C++ Always Result in Undefined Reference?

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.

Leave a Comment