2010-04-06 49 views
6

根據this question我理解了將C庫與C++代碼鏈接起來的目的。現在假設如下:在頭文件中聲明'extern「C」'到C++共享庫的效果是什麼?

我有一個'.so'共享庫,用C++編譯器編譯。頭部有一個'typedef stuct'和一些函數聲明。如果標題包含extern「C」聲明...

#ifdef __cplusplus 
extern "C" 
{ 
#endif 

    // typedef struct ...; 
    // function decls 

#ifdef __cplusplus 
} 
#endif 

...有什麼影響?具體來說,我想知道是否有任何有害的副作用,因爲共享庫被編譯爲C++,而不是C.

是否有任何理由在這種情況下有外部「C」聲明?

+0

你的庫只能從C++調用,還是你需要從C調用庫嗎? – 2010-04-06 21:06:20

回答

11

這很重要,因此編譯器不會命名爲mangle。 C++使用名稱修飾來區分具有運算符重載的函數。

運行 「的/ usr/bin中/ nm」 是針對二進制,看看C++做你的函數名: _ZSt8_DestroyIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiEvT_S7_SaIT0_E

的extern 「C」 防止名字改編。

IIRC,它使程序可以在運行時動態鏈接符號。這是「插件」類型體系結構的常見現象。

+0

感謝您的信息。我從包括頭文件在內的客戶角度思考,而不是導出名稱的庫。 – 2010-04-06 20:09:35

4

編譯C++的方法名稱的變化(壓延) - 你將無法調用該方法從另一個DLL/EXE使用C.

爲了保持你所需要的類和方法名將它們編譯爲「C」而沒有名稱混亂。

該庫仍然是一個C++庫,但它將其一些聲明(extern「c」塊中的聲明)公開爲C方法。

3

#ifdef看守extern聲明是告訴C鏈接器該符號具有C(unmangled)符號表條目。 #ifdef確保在由C編譯器編譯的代碼單元(文件)中沒有影響。

0

一個損害使用extern "C"用於C++ API是,它可以避免擁有功能重載:

extern "C" 
{ 
    // ILLEGAL - C linkage does not support function overloading 
    void foo(int x); 
    void foo(const char *str); 
} 
+1

使用'extern「C」'的意義在於C和C++代碼共享一個API,而C是最低公分母,因此您必須遵守C編譯器強制執行的規則。如果它*是一個C++ API,那麼你不會使用'extern「C」'並且只用C++編譯器進行編譯,一切都會好起來的。 – quamrana 2010-04-06 20:46:06

+1

@quamrana - 他的問題是「對C++共享庫有什麼影響」。目前還不清楚他是否需要從C代碼中調用他的庫。 – 2010-04-06 20:52:38

0

#ifdef在示例意味着只有一個C++編譯器將看到extern纏繞頭文件,其將意味着它會產生沒有損壞的名稱。 C編譯器沒有看到extern(它不會理解),但總是會生成非重名的名稱。

這意味着C和C++編譯器在它們的目標文件中會產生相同的符號,因此無論哪種編譯器都會爲所聲明的函數生成目標代碼,所有目標文件都將成功鏈接,因爲符號具有相同的鏈接和相同的名稱。

靜態鏈接或與共享庫鏈接應該沒有影響。

相關問題