2011-11-03 10 views
5

私はextern "C"の使い方を知っていますが、使用する必要がある条件は何ですか?extern "C"はいつ使用しますか?

extern "C"は任意の名前マングリング に中括弧内のコードを実行することではないC++コンパイラに指示します。これにより、C++内の からC関数を呼び出すことができます。例えば

#include <string.h> 

int main() 
{ 
    char s[] = "Hello"; 
    char d[6]; 

    strcpy_s(d, s); 
} 

これはVC++でコンパイル罰金ながら。しかし時にはこれは次のように書かれています:

extern "C" { 
#include <string.h> 
} 

私はポイントが表示されません。 extern "C"が必要な実際の例はありますか?

+7

代わりの名前の符号化を避けるために、 'を'ハッキングし、使用''ヘッダ。 –

+0

@AlexandreC .: ''ヘッダを使用することは絶対にお勧めできません。 ''ヘッダは、グローバル名前空間に識別子を置くことは保証されていません。したがって、グローバル名前空間識別子が他のコンパイラに移動されたときにそれに依存するコードを破壊します。また、 ''ヘッダーは、実際にはグローバル名前空間に識別子を配置することができるため、理論上は、非汚染グローバル名前空間に依存するコードを破ることもできます。 "理論的には"あまりにも漠然としている。少なくとも1人の馬鹿がそれをしました。だから、それらを使用しないでください。 –

+0

@ AlfP.Steinbach:C++を書くなら、 ''を使ってください。あなたがCを書くなら、 ''を使い、**あなたのコードをCコンパイラ**でコンパイルしてください。言語を混ぜるのは良い考えではありません。 –

答えて

4

ライブラリから関数をエクスポートする場合は、extern "C"をよく使用します。 C++のネームマングリングを無効にしないと、ライブラリのクライアントが関数の名前をつけるのが非常に難しくなります。同様に、他の方向に進むとき、Cリンケージでエクスポートされた関数をインポートするとき。

6

extern "C"を使用すると、ヘッダーファイルとC++オブジェクトファイル内の名前のマングリングを防ぐことができます。は、既にmanglingせずにコンパイルされたライブラリまたはオブジェクトです。

例えば、widgetというライブラリがCコンパイラでコンパイルされていて、公開されているインターフェイスがマングルされていないとします。

コードにそのままヘッダーファイルを含めると、という名前になっているとみなされ、それらのコード化されたバージョンは、リンカーに検索させるものです。

しかし、あなたは[email protected]_float_charptrのようなものとwidgetライブラリを求められますので、あなただけの問題に実行するつもり、functionを掲載しております。

しかし、あなたがそれを含める場合:

extern "C" { 
    #include "widget.h" 
} 

あなたのコンパイラが、それはfunction、非マングル化されたバージョンを使用しようとすべきであることを知っているだろう。だ

はなぜ、Cのもののためのヘッダファイルで次のようなものが表示されます、C _or C++プログラムに含まれることを意図:

#ifdef __cplusplus 
    extern "C" { 
#endif 

// Everything here works for both C and C++ compilers. 

#ifdef __cplusplus 
    } 
#endif 

あなたはこの、#ifdef行が含まれるようにCコンパイラを使用している場合extern "C"が消えます。 C++コンパイラ(__cplusplusが定義されている)の場合は、すべてが非字句になります。

+0

なぜ2番目の '#ifdef __cplusplus'があるのですか? – user103214

+0

@ user974191:それは閉じ括弧用です。そうでない場合、中括弧はアンバランスになります。 – paxdiablo

1

Cで書かれたライブラリとリンクすると、externはリンカーが関数を見つけることができるように、コンパイラに名前を飾らないように指示します。 C++では、関数名などはリンカーに関する情報を持っています。その名前に含まれる引数の型とサイズ

1

バイナリBから呼び出す関数を公開するバイナリライブラリAを作成している場合。

AがA.dll、BがB.exeで、Windowsシステムを使用しているとします。

Cは、BがAを呼び出す方法を知っているようなバイナリレイアウトを記述していません。通常、この問題は、同じコンパイラを使用してAとBを生成することによって回避されます。これにより、関数がC言語で公開されます。 Cはバイナリ形式を記述しているため、異なるコンパイラのバイナリが互いに通信できるようになっています。

参照: http://en.wikipedia.org/wiki/Application_binary_interface http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B

1

場合は、あなたのC++コードの内部に、あなた#include(Cでコーディング)外部ライブラリのヘッダと関数がextern "C"を宣言されていないがある場合、彼らは(あなたが仕事を文句を言いませんリンク時に未定義参照を取得します)。

しかし、これらの日、人々は

(適当に#ifdef __cplusplusで保護された)Cライブラリをコーディングし、あなたがそれを知っている傾向があるためにヘッダファイルを提供し、多くの場合、そのヘッダファイルにextern "C"を入れ、おそらく理解するためのより良い方法がにありますnmユーティリティを使用して(Linuxシステムを使用していると仮定して)、ライブラリや実行可能ファイルで使用されている名前を表示します。

3

ここでは、物事が壊れて、固定するためにextern "C"が必要な具体例です。

module.h

int f(int arg); 

module.c

int f(int arg) { 
    return arg + 1; 
} 

main.cpp

#include "module.h" 

int main() { 
    f(42); 
} 

私はCとC++を混在させているので、これはリンクしません(2つのオブジェクトファイルのうち、1つだけがそのC++のマングルド名でfを知っています)。

おそらく、この問題を解決するためにクリーンな方法は、CおよびC++の両方と互換性のあるヘッダファイル行うことである。

module.h

#ifdef __cplusplus 
    extern "C" { 
#endif 

int f(int arg); 

#ifdef __cplusplus 
    } 
#endif 
+0

+1これは私が探していたものを説明しています。 – user103214

関連する問題