Original link: https://blog.vvzero.com/2023/07/03/learn-extern-c-in-cpp-again/
This article is part of the “Jade Attack Project”, translated from the answer of Ciro Santilli in https://stackoverflow.com/questions/1041866/what-is-the-effect-of-extern-c-in-c
Understand the role of extern “C” through disassembly
main.cpp
1 |
void f () {} |
Compile the above code into a binary in ELF format, and then disassemble:
1 |
g++ -c -std=c++11 -Wall -Wextra -pedantic -o main.o main.cpp |
Extract part of the output:
1 |
8: 0000000000000000 7 FUNC GLOBAL DEFAULT 1 _Z1fv |
visible:
- The names of
ef
andeg
in the symbol table are the same as those in the original code - Other symbols have been modified, we can use the
c++filt
tool to restore its original appearance:
1 |
$ c++filt_Z1fv |
So, we need to use extern "C"
in the following two cases:
- Calling C code in C++: tells
g++
that undecorated symbol names generated bygcc
may be encountered - Calling C++ code in C: Let
g++
generate undecorated symbol names forgcc
to call
Certain codes that cannot be used in extern “C”
Obviously, any language feature that requires C++ name decoration cannot be written in extern "C"
:
1 |
extern "C" { |
A minimal runnable code sample calling C code from C++
Calling C code from C++ is simple: every C function has just an undecorated symbol name, so no extra work is required.
main.cpp
1 |
# include <cassert> |
ch
1 |
#ifndef C_H |
cc
1 |
# include "ch" |
run:
1 |
g++ -c -o main.o -std=c++98 main.cpp |
If there is no extern "C"
, the linker will report an error:
1 |
main.cpp:6: undefined reference to `f()' |
Because g++
will look for a modified f
, but gcc
will not compile the modified symbol name.
A minimal runnable code sample calling C++ code from C
Calling C++ code from C is a little more difficult: we need to manually manage all the functional interfaces exposed to C and make them undecorated at compile time.
code show as below:
main.c
1 |
# include <assert.h> |
cpp.h
1 |
#ifndef CPP_H |
cpp.cpp
1 |
# include "cpp.h" |
run:
1 |
gcc -c -o main.o -std=c89 -Wextra main.c |
If extern "C"
is not added, an error will be reported:
1 |
main.c:6: undefined reference to `f_int' |
Because g++
generates decorated symbol names, but gcc
can’t understand them.
Where is the extern “C” when I include the standard library C headers in C++?
- C++ version of C header files, such as
cstdio
may be implemented by compiling the macro#pragma GCC system_header
, according to https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html : On some platforms, such as RS/ When compiling C++ code on 6000 AIX, GCC will implicitly include all system header files with extern “C”. But I’m not entirely sure. - POSIX standard header files, such as
/usr/include/unistd.h
will use__BEGIN_DECLS
macro, and__BEGIN_DECLS
will be defined asextern "C" {
. See https://stackoverflow.com/questions/8087438/do-i-need-an-extern-c-block-to-include-standard-posix-c-headers/8087539#8087539 for details.
This article is transferred from: https://blog.vvzero.com/2023/07/03/learn-extern-c-in-cpp-again/
This site is only for collection, and the copyright belongs to the original author.