1. 背景
為了工作需要奈辰,在抽離一個(gè)開源庫組件的時(shí)候,編譯成功鏈接卻失敗乱豆,查找原因發(fā)現(xiàn)測試文件使用的是C++語言奖恰,而庫的組件使用的是C語言,具體原因記錄與此宛裕。
2. 現(xiàn)場
為了測試瑟啃,寫了一個(gè)單獨(dú)的簡單案例:
新建win32
工程,建立三個(gè)文件揩尸,分別是test.c
蛹屿、test.h
和main.cpp
。
main.cpp
#include "test.h"
int main()
{
test(1);
return 0;
}
test.h
#ifndef _TEST_H_
#define _TEST_H_
void test(int a);
#endif
test.c
#include "test.h"
void test(int a)
{
}
編譯運(yùn)行:
3. 原因
編譯成功岩榆,鏈接失敗错负,很顯然代碼中已經(jīng)實(shí)現(xiàn)了test
函數(shù),為了查找原因朗恳,直接打開vs命令行工具查看一下編譯后的符號(hào)表都有什么湿颅。
進(jìn)入Debug目錄载绿,執(zhí)行dumpbin /SYMBOLS test.obj
粥诫。
答案很顯然,編譯test.c
生成的符號(hào)是_test
崭庸,而現(xiàn)在要找的是void __cdecl test(int)" (?test@@YAXH@Z)
怀浆,結(jié)果當(dāng)然是無法找到的谊囚。
為了進(jìn)一步確認(rèn)答案,將test.c
改為test.cpp
执赡,重新編譯镰踏,查看符號(hào)表。
對于C語言生成的符號(hào)表和C++語言生成的符號(hào)表差距很大沙合,原因無非是C++支持了很多新的功能奠伪,原來的符號(hào)表生成規(guī)則已經(jīng)無法滿足。
例如:重載首懈、多態(tài)等機(jī)制绊率。
為了解決這個(gè)問題,C++語言引入了另一種語法來解決這個(gè)問題究履。
4. 結(jié)論
對于C語言編寫的程序來說滤否,未來可能被C語言或者C++語言的用戶所使用,大部分解決的方法是:
#ifdef __cplusplus
extern "C" {
#endif
// ...
#ifdef __cplusplus
}
#endif
直接在C語言中使用extern "C"
會(huì)報(bào)語法錯(cuò)誤最仑,因?yàn)樵撜Z法是C++語法藐俺,對于C語言來說,聲明該接口是C語言編寫的顯然沒有任何意義,它的目標(biāo)是使用C++語言的用戶泥彤;而對于C++用戶欲芹,該聲明卻是必須的,因?yàn)镃和C++語言編寫的函數(shù)的符號(hào)表生成結(jié)果是不一致的吟吝,除非你在編譯C文件的時(shí)候明確用C++編譯器耀石,那就沒什么問題了。