extern "C" 是 C++ 與 C 互操作的核心橋樑,指示編譯器對被修飾的函數/變量採用 C 語言鏈接約定(不進行 Name Mangling),使 C++ 代碼能正確調用 C 庫,或 C 代碼調用 C++ 導出符號。
為了支持函數重載,C++ 編譯器將函數簽名編碼進符號名:
void foo(int x, int y); // C 編譯器符號:_foo // C++ 編譯器符號:_foo_int_int / ?foo@@YAXHH@Z (MSVC) 等
若 C++ 直接調用 C 庫導出的 foo,鏈接器會尋找修飾後的名字 → 找不到 → LNK2019。
#ifndef MY_HEADER_H
#define MY_HEADER_H
#ifdef __cplusplus
extern "C" {
#endif
// C 風格聲明
void c_api_init();
int c_api_compute(int a, int b);
#ifdef __cplusplus
}
#endif
#endif // MY_HEADER_H
// mylib.c
#include <windows.h>
#define EXPORT __declspec(dllexport)
EXPORT void hello() { MessageBox(NULL, "Hi from C DLL", "DLL", MB_OK); }
// main.cpp
extern "C" void hello(); // 告訴 C++ 編譯器:這個符號按 C 方式鏈接
int main() {
HMODULE h = LoadLibrary("mylib.dll");
auto fn = (void(*)())GetProcAddress(h, "hello"); // 符號名就是 "hello"
fn();
FreeLibrary(h);
}
// 單個聲明
extern "C" void foo(int);
// 塊聲明
extern "C" {
void bar(double);
int globalVar;
#include "c_header.h" // 批量包含 C 頭文件
}
extern "C" 以內層為準。extern "C"。extern "C" 實體(跨命名空間也不行)。extern "C" 強制外部鏈接,不能配合 static(但 static 在塊內合法,內部鏈接不產生語言鏈接)。
extern "C"相當於 JNI 中的native關鍵字 +System.loadLibrary:告訴運行時「這個符號按 C ABI 查找,不要按 C++/Java 的名字規則找」。