Extern C Usage

轉錄自 http://hatupsidedown.blogspot.com/2007/02/extern-c.html
使用 extern "C" 目的在於解決混用C與C++時所發生的問題。

事實1. 副檔名為 .c 的檔案由C compiler編譯
事實2. 副檔名為 .cpp 的檔案由C++ compiler編譯
事實3. 每個function 都有供內部使用的名稱,且在C與C++之下的內部名稱並不相同。例如

void plus(int a, int b);

其在C之下的內部名稱可能是 _plus;
而在C++之下的內部名稱卻是 _plus_int_int (註:也正因為如此C++才能overload名字相同,但參數的變數型態不同的functions)

[Generated] (被產生)
事實4. 當compiler在編譯一個function時,compiler會產生一個內部名稱。以下是各種可能發生的情況:

G1. 當 C compiler 看到一個正常的 function 的宣告(declaration, function prototype), 它永遠都產生C style 的內部名稱。
G2. 當C++ compiler看到一個正常的function的宣告, 它產生 C++ style的內部名稱。
G3. 當C++ compiler看到一個使用 extern "C" function的宣告, 它產生C style的內部名稱。

[Used] (被使用)
事實5. 當compiler在編譯一個function call時,compiler 會它會使用內部名稱。之後,linker再用該內部名稱去找那個function。以下是各種可能發生的情況:

U1. 當 C compiler 看到一個 function call (該function 正常宣告), 它會使用C style的內部名稱(永遠如此)。之後,linker用該內部名稱去locate該function。
U2. 當 C++ compiler 看到一個 function call(該function正常宣告), 它會使用 C++ style的內部名稱。之後,linker用該內部名稱去locate該function。
U3. 當 C++ compiler 看到一個function call (該function 的宣告出現在 extern "C" scope(一對大括弧)中, 它會使用 C style的內部名稱。之後,linker用該內部名稱去locate該function。

事實6. 當 [Generated] 和 [used] 的內部名稱不是相同的style, 則Linking時會產生連接錯誤。

以下是一些例子,請下載檔案並解壓縮。共有五個case. 每個case一開始都無法成功地compile或Link。原始檔中並提供使compilation或Linking成功的修改方法。

case1: (G3, U2) —> (G2, U2)
case2: (G2, U1) —> (G3, U1)
case3: (G1, U2) —> (G1, U3)
case4: (G2, U1) —> (G2, U1) //與Case2基本上相同,注意,依此法修改後問題仍未解決。
case5: (G1, U2) —> (G1, U3)


C call C++ function

cFile.c


#include "cppFile.h"
#include <stdio.h>

int main()
{
        printf("%d",add(1,2));
        return 0;
}

cppFile.h


extern "C" {
int add( int x, int y );
}
// no extern "C" will cause link error

cppFile.c
#include "cppFile.h"

int add( int x, int y )
{
        return x + y;
}
C++ call C function

a.cpp


extern "C" {
        #include "cFile.h"
}
// if no extern "C", it will compile error

#include <iostream>

using namespace std;

int main()
{
        cout << add(1,2);
        return 0;
}

cFile.h
extern int add( int x, int y );

cFile.c
#include "cFile.h"

int add(int a,int b)
{
        return a+b;
}
c
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License