如下代碼:
/*C語言頭文件:Max.h*/
#ifndef _MAX_H_
#define _MAX_H_
int Max(int nA,int nB)
#endif
/*C語言實現文件:Max.c*/
#include "Max.h"
int Max(int nA,int nB)
{
return((nA-nB)?(nA):(nB));
}
/*C++語言調用文件*/
#include "Max.h"
int _tmain(int argc,char* argv[])
{
int nMax = Max(1,2);
return 0;
}
上述代碼在Visual C++中編譯會出錯(error LNK2019:無法解析的外部符號"int __cdecl Max(int,int)"(?Max@@YAHHH@Z),該符號在函數_wmain中被引用
如果把上述的Max.h代碼修改如下:
/*C語言頭文件*/
#ifndef __MAX_H__
#define __MAX_H__
#ifdef __cplusplus
extern "C"{
#endif
int Max(int nA,int nB);
#ifdef __cplusplus
};
#endif
#endif
編譯通過
結論:在C++中調用C的代碼必須把原來的C語言聲明放到extern "C"{/*code*/}中,否則在C++中無法編譯通過
原因:C和C++具有完全不同的編譯和鏈接方式。C語言編譯器編譯函數時不帶函數的類型和作用域信息,只包含函數符號名字;而c++編譯器為了實現函數的重載,在編譯時會帶上函數的類型和作用域信息。
例如:假如某一函數原型為:int Func(int nA,int nB)
C語言編譯器把函數編譯成類似_Func的符號,C鏈接器只要找到這個符號就可以連接成功,實現調用。而在C++語言中,編譯器會檢查參數類型和作用域信息,上述函數原型會編譯成_Z_Func_int_int這樣的符號。在鏈接過程中,C++鏈接器會在函數原型所在模塊生成的目標文件中查找__Z_Func_int_int.
總結:C++中調用C代碼的3種具體實現方式
1.修改C代碼的頭文件,當其被用於C++代碼時,在聲明中加入exter "C" 上例中在Max.h中加入extern "C" int Max(int nA,int nB);
2.在C++代碼中(Main.cpp)重新聲明一下C函數,在重新聲明時添加extern "C".
#include "Max.h"
extern "C" int Max(int nA,int nB);
3.在包含C頭文件(Main.cpp)時,添加extern "C".
extern "C"{
#include "Max.h"
}
注意:extern "C" 一定要加在C++的代碼文件中才起作用