Question
What exactly does adding extern "C" to C++ code do?
For example:
extern "C" {
void foo();
}
What effect does this have on the function declaration, and when should it be used?
Short Answer
By the end of this page, you will understand what extern "C" means in C++, why it is used when working with C code, how it affects linkage and name mangling, and what it does not change about a function.
Concept
extern "C" tells the C++ compiler to use C linkage for the declared functions or variables.
The main reason this matters is name mangling.
What is name mangling?
C++ supports features like:
- function overloading
- namespaces
- classes
- templates
To support these features, C++ compilers often change function names in the compiled output. For example, a function like:
void foo(int);
might be turned into a symbol name that encodes its parameter types.
C does not do this in the same way. A C function named foo is usually exported simply as foo.
What extern "C" changes
When you write:
extern "C" void foo();
or:
extern "C" {
;
}
Mental Model
Think of a compiled function name like a label on a package.
- In C, the label is usually simple:
foo - In C++, the label may include extra hidden details:
foo__int_version(conceptually)
The linker is like a delivery worker matching package labels.
If a library exports foo, but your C++ code asks for a more detailed C++-style label, the delivery worker cannot find the package.
extern "C" says:
Use the simple C-style label for this function.
So both sides agree on the same name.
Syntax and Examples
Basic syntax
Single declaration
extern "C" void foo();
Multiple declarations
extern "C" {
void foo();
int add(int a, int b);
}
Example: calling a C function from C++
Imagine this C library file:
/* mathlib.c */
int add(int a, int b) {
return a + b;
}
And this header:
/* mathlib.h */
int add(int a, int b);
If you include that header in C++ code, you usually wrap it like this:
Step by Step Execution
Consider this C function:
/* library.c */
void foo() {
}
And this C++ declaration:
extern "C" void foo();
What happens step by step
- The C compiler compiles
library.c. - It exports a symbol named something like
foo. - The C++ compiler sees
extern "C" void foo();. - It records that
fooshould use C linkage. - When the C++ code calls
foo(), it looks for the plain symbolfoo. - The linker matches the call to the C-compiled function successfully.
What if extern "C" is missing?
Suppose the C++ code is instead:
void foo;
Real World Use Cases
Using C libraries from C++
Many system and third-party libraries are written in C. Examples include:
- operating system APIs
- embedded libraries
- cryptography libraries
- image/audio processing libraries
C++ code uses extern "C" so those functions can be linked correctly.
Writing libraries meant for multiple languages
A library may be implemented internally in C++ but expose a small C-compatible API so that it can be called from:
- C
- Rust
- Python bindings
- Go FFI
- other native languages
In these cases, exported functions are often declared with extern "C".
Plugin entry points
Some plugin systems expect a function with a known exported name such as:
extern "C" int plugin_init();
This avoids compiler-specific C++ mangled names.
Embedded and systems programming
Firmware, drivers, and low-level interfaces often mix C and C++ code. extern "C" helps keep interfaces stable across language boundaries.
Real Codebase Usage
In real projects, extern "C" is usually not scattered randomly through application code. It appears at boundaries.
Common patterns
1. Wrapping C headers
extern "C" {
#include "legacy_lib.h"
}
This is common when integrating an older C library into a C++ project.
2. C-compatible public API
A C++ library may hide classes internally and expose simple functions:
extern "C" void* create_engine();
extern "C" void destroy_engine(void* engine);
This avoids exposing C++ ABI details directly.
3. Stable entry points
Applications or runtimes may search for functions by exact symbol name. extern "C" ensures predictable exported names.
Related patterns developers use alongside it
- Validation: check pointers and arguments at the API boundary
Common Mistakes
1. Thinking extern "C" means “compile this as C”
It does not. The file is still compiled as C++.
extern "C" void foo() {
// This is still C++ code
}
You can still use many C++ features in the implementation, subject to normal rules.
2. Forgetting to use it when including a C header in C++
Broken example:
#include "clib.h"
If clib.h declares C functions but does not protect them for C++, linking may fail.
Better:
#ifdef __cplusplus
extern "C" {
#endif
void foo();
#ifdef __cplusplus
}
#endif
3. Trying to overload extern "C" functions
Comparisons
| Concept | What it affects | Typical use | Supports overloading? |
|---|---|---|---|
| Normal C++ declaration | C++ linkage and name mangling | Regular C++ code | Yes |
extern "C" declaration | C linkage, usually no C++ mangling | Interfacing with C or stable exported symbols | No practical overloading |
extern in C/C++ | Storage/linkage declaration across translation units | Referencing global variables/functions defined elsewhere | Not about C linkage by itself |
extern vs extern "C"
These are related but different:
externalone usually means “this name is defined elsewhere”extern "C"means “use C linkage for this declaration”
Cheat Sheet
Quick reference
Basic forms
extern "C" void foo();
extern "C" {
void foo();
int add(int a, int b);
}
What it does
- Uses C linkage
- Usually disables C++ name mangling for the declaration
- Helps C++ link with C code
What it does not do
- Does not compile the code as C
- Does not make C++ syntax invalid
- Does not automatically make an API safe for all languages
Common use case
Wrap C headers so they work in C++:
#ifdef __cplusplus
extern "C" {
#endif
/* declarations */
#ifdef __cplusplus
}
FAQ
What does extern "C" mean in C++?
It means the declared function or variable uses C linkage instead of normal C++ linkage.
Does extern "C" prevent name mangling?
In practice, yes for the declared symbols. That is one of its main purposes.
Is extern "C" required when calling C from C++?
Yes, if the declarations are seen by a C++ compiler and need to match symbols produced by C code.
Can I use extern "C" with C++ member functions?
Not in the normal way for class member functions. C linkage is mainly used for free functions and variables at the interface boundary.
Can extern "C" functions be implemented in C++?
Yes. The implementation can be compiled as C++, while the function keeps C linkage.
Does extern "C" make a function callable from Python or Rust?
Not by itself. It helps create a C-compatible symbol, but you still need compatible types and a proper foreign-function interface.
Why do C headers use #ifdef __cplusplus around extern "C"?
Because extern "C" is valid in C++, not in C. The preprocessor guard makes the same header work in both languages.
Mini Project
Description
Create a tiny C library and call it from a C++ program. This demonstrates the real purpose of extern "C": making symbol names match between C and C++ so the linker can connect them correctly.
Goal
Build a working example where a C++ program successfully calls functions implemented in C using extern "C".
Requirements
- Create a C header that declares at least two functions.
- Make the header usable from both C and C++.
- Implement the functions in a C source file.
- Call the functions from a C++
mainprogram. - Print the returned results to confirm linking works.
Keep learning
Related questions
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.
Definition vs Declaration in C and C++: What’s the Difference?
Learn the difference between declarations and definitions in C and C++ with simple examples, common mistakes, and practical usage.
Difference Between #include <...> and #include "..." in C and C++
Learn the difference between #include with angle brackets and quotes in C and C++, including search paths, examples, and common mistakes.