extern “C“ in C++
English:extern "C"tells the C++ compiler to use C linkage for a declaration or definition, which mainly disables C++ name mangling.
中文:extern "C"告诉 C++ 编译器:这个声明或定义要使用C 链接方式,最主要的效果就是关闭 C++ 的名字重整。
English:It does not mean “compile this file as C”. It only changes symbol linkage.
中文:它并不表示“把这个文件按 C 来编译”,它只是改变符号链接方式。
实验 1:.c和.cpp都用g++编译
.c & .cpp both compile with g++
main.cpp
#include <iostream> #include "test.h" // extern "C" void show(); void test01() { show(); } int main() { test01(); return EXIT_SUCCESS; }test.h
#include <stdio.h> void show();test.c
#include "test.h" void show() { printf("hello world.\n"); }both get C++ linkage
g++ main.cpp test.c -o main
shaoyoulu@shaoyoulu:~/Code/extern$ g++ main.cpp test.c -o main shaoyoulu@shaoyoulu:~/Code/extern$ ./main hello world.English:When you rung++ main.cpp test.c -o main, both files are compiled as C++ translation units. The.csuffix does not force C mode when the compiler isg++.
中文:当你执行g++ main.cpp test.c -o main时,这两个文件都会被当成C++ 翻译单元编译。.c后缀并不会强制让g++进入 C 模式。
English:That is why the program works even withoutextern "C": both declaration and definition are C++ linkage, so they match.
中文:这就是为什么即使没有extern "C",程序也能运行:因为声明和定义都被当成 C++ 链接方式,所以符号是匹配的。
English:This experiment proves only one thing:g++compiles.cfiles as C++ when you askg++to compile them.
中文:这个实验只证明了一件事:当你让g++去编译时,它会把.c文件也按 C++ 处理。
实验 2:main.cpp用g++,test.c用gcc,但没有extern "C"
.cpp compile with g++, .c compile with gcc
withoutextern "C" void show();
shaoyoulu@shaoyoulu:~/Code/extern$ g++ -c main.cpp -o main.o shaoyoulu@shaoyoulu:~/Code/extern$ gcc -c test.c -o test.o shaoyoulu@shaoyoulu:~/Code/extern$ g++ main.o test.o -o main /usr/bin/ld: main.o: in function `test01()': main.cpp:(.text+0x9): undefined reference to `show()' collect2: error: ld returned 1 exit status shaoyoulu@shaoyoulu:~/Code/extern$undefined reference to `show()'
English:This is the real mixed C/C++ test.gcccompilestest.cas C, soshowhas C linkage.g++compilesmain.cppas C++, soshow()in the declaration has C++ linkage by default.
中文:这才是真正的 C/C++ 混合测试。gcc把test.c按 C 编译,所以show是 C 链接;g++把main.cpp按 C++ 编译,所以show()的声明默认是 C++ 链接。
English:The linker then sees two different symbols: one unmangled C symbol and one mangled C++ symbol. So it reportsundefined reference to show().
中文:于是链接器看到的是两个不同的符号:一个是未重整的 C 符号,一个是 C++ 重整后的符号,所以报undefined reference to show()。
实验 3:在main.cpp中加上extern "C" void show();
withextern "C" void show();
main.cpp
#include <iostream> //#include "test.h" extern "C" void show(); void test01() { show(); } int main() { test01(); return EXIT_SUCCESS; }shaoyoulu@shaoyoulu:~/Code/extern$ g++ -c main.cpp -o main.o shaoyoulu@shaoyoulu:~/Code/extern$ gcc -c test.c -o test.o shaoyoulu@shaoyoulu:~/Code/extern$ g++ main.o test.o -o main shaoyoulu@shaoyoulu:~/Code/part1/extern$ ./main hello world. shaoyoulu@shaoyoulu:~/Code/extern$English:Now the C++ compiler is told to treatshowas a C-linked symbol. It no longer mangles the name, so the declaration matches the C definition compiled bygcc.
中文:这时 C++ 编译器被告知:show是 C 链接符号,不要重整名字。于是这个声明就能和gcc编译出来的 C 定义匹配上。
English:That is why the program links and runs correctly.
中文:这就是为什么程序能正确链接并运行。
important concepts to emphasize
1extern "C"的本质
English:extern "C"is a linkage specification, not a storage class and not a compiler switch.
中文:extern "C"是一种链接说明,不是存储类别,也不是编译器开关。
English:Its main purpose is to make C+±compiled code produce C-compatible symbols.
中文:它的主要目的,是让 C++ 编译出来的代码生成C 兼容的符号名。
2 C++ 为什么需要它
English:C++ supports function overloading, namespaces, and more advanced type information, so it encodes extra information into symbol names. This is name mangling.
中文:C++ 支持函数重载、命名空间以及更复杂的类型信息,所以它会把额外信息编码进符号名,这就是名字重整。
English:C does not need that, so C symbols are simple and unmangled.
中文:C 不需要这些机制,所以 C 的符号名通常是简单直接的、不会重整。
3extern "C"不能做什么
English:extern "C"does not magically make C code legal in a C++ file. It only changes linkage.
中文:extern "C"不会让 C 代码在 C++ 文件里“自动合法”,它只改变链接方式。
English:It also does not make two different function signatures compatible. The parameter types and return type still must match.
中文:它也不会让两个不同函数签名变成兼容。参数类型和返回值类型仍然必须匹配。
extern "C"标准写法
头文件写法 / Header pattern
test.h
#ifdef __cplusplus extern "C"{ #endif #include <stdio.h> void show(); #ifdef __cplusplus } #endifEnglish:This is the standard mixed C/C++ header pattern.
中文:这是标准的 C/C++ 混合头文件写法。
English:If the header is included by C++ code,showgets C linkage. If it is included by C code, theextern "C"part is ignored because__cplusplusis not defined.
中文:如果这个头文件被 C++ 代码包含,show就会获得 C 链接;如果被 C 代码包含,因为__cplusplus没定义,extern "C"那部分就会被跳过。
main.cpp
#include <iostream> #include "test.h" void test01() { show(); } int main() { test01(); return EXIT_SUCCESS; }test.c
#include "test.h" void show() { printf("hello world.\n"); }shaoyoulu@shaoyoulu:~/Code/extern$ g++ -c main.cpp -o main.o shaoyoulu@shaoyoulu:~/Code/extern$ gcc -c test.c -o test.o shaoyoulu@shaoyoulu:~/Code/extern$ g++ main.o test.o -o main shaoyoulu@shaoyoulu:~/Code/part1/extern$ ./main hello world. shaoyoulu@shaoyoulu:~/Code/extern$extern "C"出现在声明端还是定义端
English:In mixed-language projects, the most common practice is to putextern "C"in the header declaration, so both C and C++ translation units stay consistent.
中文:在混合语言工程中,最常见的做法是把extern "C"放在头文件声明处,这样 C 和 C++ 的翻译单元都能保持一致。
English:If both declaration and definition are compiled as C++, then both sides must agree on C linkage if you want a C symbol.
中文:如果声明和定义都按 C++ 编译,那么两边都必须约定使用 C 链接,否则不会得到 C 符号。
extern "C"和重载
English:Functions declared withextern "C"cannot be overloaded, because C linkage does not carry type information for overload resolution.
中文:被声明为extern "C"的函数不能重载,因为 C 链接不携带用于重载解析的类型信息。
English:This is another important reason whyextern "C"is only for interface boundaries.
中文:这也是为什么extern "C"主要用于接口边界,而不是随便在内部代码里乱用。
纯 C++,不需要extern "C"
English:Show that compiling everything withg++makes the program work because everything is C++.
中文:先展示“全部用g++编译”时程序能工作,因为整个程序都被当成 C++。
真正的 C + C++ 混编,必须用extern "C"
English:Then showg++ main.cpp+gcc test.c, and let it fail withoutextern "C".
中文:然后展示g++ main.cpp+gcc test.c,在没有extern "C"时失败。
加上extern "C"后成功
English:Finally, add theextern "C"guard in the header or declaration, and show the link succeeds.
中文:最后加上头文件里的extern "C"保护,展示链接成功。
Misconceptions
English:Misconception 1:.cfiles are always compiled as C.
中文:误区 1:.c文件总是按 C 编译。
English:Correction: the compiler determines the language mode.g++will compile.cfiles as C++.
中文:更正:语言模式由编译器决定。g++会把.c文件按 C++ 编译。
English:Misconception 2:extern "C"changes runtime calling behavior.
中文:误区 2:extern "C"会改变运行时调用行为。
English:Correction: it mainly changes symbol linkage and mangling, not the high-level function logic.
中文:更正:它主要改变的是符号链接和名字重整,不改变函数逻辑本身。
English:Misconception 3: Onceextern "C"is added, any C and C++ code can freely mix.
中文:误区 3:加了extern "C"后,C 和 C++ 就能随便混用。
English:Correction: types, headers, memory management, and API conventions still must be compatible.
中文:更正:类型、头文件、内存管理、API 约定仍然必须兼容。