C++ 支援函式多載,編譯器會對函式名進行名稱修飾,編碼參數型別等資訊生成唯一符號。C 編譯器不修飾,符號即函式名。直接混合編譯會導致鏈接錯誤:找不到符號。
extern "C"告訴 C++ 編譯器:「以下宣告的函式採用 C 語言鏈接規約 (不修飾名稱)」。
// C++ 端
extern "C" void csayhello(char *str); // 宣告為 C 鏈接
int main() {
csayhello("Hello from C++ to C");
return 0;
}
// my_c_lib.h
#ifdef __cplusplus
extern "C" {
#endif
// 這裡放所有 C 函式宣告、結構體定義、巨集等
int c_add(int a, int b);
void c_init(void);
#ifdef __cplusplus
}
#endif
// my_c_lib.c
#include <stdio.h>
#include "my_c_lib.h"
int c_add(int a, int b) { return a + b; }
void c_init(void) { printf("C lib init\n"); }
# 編譯 C++ 檔
g++ -c cpp_main.cpp -o cpp_main.o
# 編譯 C 檔
gcc -c my_c_lib.c -o my_c_lib.o
# 鏈接 (需手動指定 C++ 標準庫)
gcc cpp_main.o my_c_lib.o -lstdc++ -o my_app
若用 g++ 鏈接 (g++ cpp_main.o my_c_lib.o -o my_app),會自動鏈接 libstdc++。
現有 C 頭檔 myheader.h:
typedef struct { int year, month, day; } Date;
int GetWeekNo(Date);
改造為支援 C++ 包含:
#ifndef MYHEADER_H
#define MYHEADER_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct { int year, month, day; } Date;
int GetWeekNo(Date);
#ifdef __cplusplus
}
#endif
#endif
關鍵細節:__cplusplus 前雙底線,大小寫敏感。巨集包裹確保 C 編譯器忽略 extern "C",C++ 編譯器啟用它。
<stdio.h>, <string.h>) 內部已包裹 extern "C",C++ 直接 #include <cstdio> 即可。extern "C" { #include "third_party.h" }extern "C" (有 this 指標、名稱修飾複雜)。需寫 C 風格包裝函式轉呼叫。extern "C" int g_var; 可共享全域變數。extern "C" 或 static,否則指標型別不匹配。extern "C" 是 C/C++ 混合編程的基石。核心口訣:「C++ 端宣告包裹,C 端正常實現,頭檔雙重防護,鏈接手動指定庫」。規範化頭檔寫法,一次封裝,雙端通用。