extern “C”總結

轉載地址:> http://www.cnblogs.com/graphics/archive/2010/12/24/1916343.html

經常看到如下代碼:

#ifdef _cplusplus
extern "C" {
#endif
#include "XXX.h"
#ifdef _cplusplus
}
#endif

解釋:

extern “C”的作用是,告訴C++編譯器,下面的代碼按照C的方式進行編譯,說白了,不要對這些函數進行名字重整(function name mangling)。通常在C++程序中使用C函數或者模塊時,需要用到這個功能。

原因:

C++爲了支持函數重載,將編譯後的函數名做了重整(mangled name),比如下面的函數

int add(int a, int b) ;

在C中編譯完的名字就是add,而在C++中,編譯完就變成了add_int_int(舉例而已,實際因編譯器而異),這樣在函數名字後面加上參數的類型,就可以區分不同的重載函數了,比如還有另一個函數

float add(float a, float b) ;

在C++中,它會被編譯成add_float_float,這就是C++區分重載函數的機制

可是問題也隨之而來

C++進行名字重整,而C不進行重整。當C++程序引用C的函數時,它會按照重整後的名字去目標文件(.obj)中去尋找對應的函數,而目標文件中存放的卻是C版本的函數,名字對不上,所以根本找不到!

怎麼辦呢?

這就是extern “C” 存在的一個原因了

它告訴C++,包含在extern “C”{ //…}塊中的東西是C版本的,你編譯的時候不要進行名字重整,否則你鏈接的時候就無法找到我!

於是上面的代碼也就不難理解了,光說不練是扯淡,上代碼

我們簡單的定義一個C頭文件和實現文件,只包含一個add函數

CClass.h 內容如下

#ifndef __CClass_H__

#define __CClass_H__

extern int add(int a, int b) ;

#endif // end __CClass_H__

CClass.c 內容如下

#include "CClass.h"

int add(int a, int b)

{

return a + b ;

}

下面我們用一個C++程序來引用這個C文件

main.cpp 內容如下


#define _cplusplus // 爲了測試,強加一句

#ifdef _cplusplus

extern "C" {

#endif

#include "CClass.h"

#ifdef _cplusplus

}

#endif

#include <iostream>

using namespace std ;

int main(void)

{

int result = add(1, 2) ;

cout << result << endl ;

system("pause") ;

return 0 ;

}

如果沒有#include 之前那些代碼而只是僅僅包含

#include "CClass.h"

你就會得到下面的錯誤

error LNK2019:unresolved external symbol “int __cdecl add(int,int)” (?add@@YAHHH@Z) referenced in function _main

顯然這是一個鏈接錯誤,因爲找不到對應的函數定義

當然你也可以簡寫成下面的形式,直接在extern “C”塊中包含你想調用的函數

extern "C"

{

int add(int a, int b) ;

};

#include <iostream>

using namespace std ;

int main(void)

{

int result = add(1, 2) ;

cout << result << endl ;

system("pause") ;

return 0 ;

}

這在C++程序中是沒有問題的,但是如果是在C程序中,則會出現編譯錯誤,因爲C中不允許extern “C”出現

另一個需要extern “C”的場合是當C程序調用C++的東西時

按照如下步驟做即可

  1. 在C++的.h文件中用extern “C”{}聲明將被C程序使用的函數

  2. 在C++的.cpp文件中實現上面的函數

  3. 在.c文件中用extern聲明要使用的C++函數

  4. 使用即可

注意:切不可在.c文件中包含C++的.h文件,那樣編譯無法通過

上代碼:

CPPClass.h中聲明add函數

#ifndef __CPPClass_H__

#define __CPPClass_H__

extern "C"

{

int add(int a, int b) ;

};

#endif // end __CPPClass_H__
}

CPPClass.cpp實現add函數

#include "CPPClass.h"

int add(int a, int b)

{

return a + b ;

main.c 內容如下

#include <stdio.h>

//#include "CPPClass.h" // 不要包含頭文件,否則編譯不過

extern int add(int a, int b) ; // 只需顯示聲明要調用的函數即可

int main(void)

{

int result = add(1, 2) ; //使用函數

printf("%d", result) ;

return 0 ;

}
發佈了23 篇原創文章 · 獲贊 16 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章