When integrating C and C++ code—common in systems programming or embedded development—one key challenge arises from C++'s name mangling mechanism. Unlike C, which preserves function names exactly as written, C++ modifies identifiers during compilation to support features like function overloading. This discrepancy can break linking between C and C++ object files unless addressed with extern "C".
Name Mangling in C++
C++ compilers encode additional semantic information—such as parameter types—in to symbol names. For instance:
int compute(int x, int y);
double compute(double x, double y);
Might become symbols like _Z7computeii and _Z7computedd. This allows overloading but makes direct linking with C ipmossible, since C expects plain, unmangled names like compute.
Role of extern "C"
The extern "C" linkage specification instructs the C++ compiler to suppress name mangling for enclosed declarations, producing C-compatible symbol names. This enables bidirectional calls between C and C++.
Practical Usage Patterns
Calling C Functions from C++
A C header should wrap declarations in an extern "C" block, guarded by __cplusplus:
// math_ops.h
#ifndef MATH_OPS_H
#define MATH_OPS_H
#ifdef __cplusplus
extern "C" {
#endif
int multiply(int a, int b);
#ifdef __cplusplus
}
#endif
#endif
The corresponding C implementation remains unchanged:
// math_ops.c
#include "math_ops.h"
int multiply(int a, int b) {
return a * b;
}
Now, C++ code can include the header and link successfully:
#include <iostream>
#include "math_ops.h"
int main() {
std::cout << multiply(6, 7) << '\n';
}
Exposing C++ Functions to C
To call a C++ function from C, declare it with extern "C" in both header and implementation:
// logger.h
#ifndef LOGGER_H
#define LOGGER_H
#ifdef __cplusplus
extern "C" {
#endif
void log_message();
#ifdef __cplusplus
}
#endif
#endif
// logger.cpp
#include <cstdio>
#include "logger.h"
void log_message() {
std::puts("Message from C++");
}
Then use it in C:
#include "logger.h"
int main() {
log_message();
return 0;
}
Without extern "C", the C linker would fail to resolve log_message due to symbol name mismatch.