Using extern "C" for C and C++ Interoperability

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.

Tags: C C++ interoperability linkage extern C

Posted on Mon, 07 Sep 2026 16:26:40 +0000 by sean paul