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
efandegin the symbol table are the same as those in the original code - Other symbols have been modified, we can use the
c++filttool 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 bygccmay be encountered - Calling C++ code in C: Let
g++generate undecorated symbol names forgccto 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
cstdiomay 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.hwill use__BEGIN_DECLSmacro, and__BEGIN_DECLSwill 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.