5

使い方はわかったけど、使わ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"か?

4

6 に答える 6

7

マングリングなしで既にコンパイルされているライブラリまたはオブジェクトextern "C"のヘッダー ファイルおよび C++ オブジェクト ファイル内の名前のマングリングを防止するために使用します。

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

ヘッダー ファイルをそのままコードにインクルードすると、名前マングルされていると見なされ、それらのマングルされたバージョンがリンカーに探すように指示されます。

ただし、次のようなものを要求するfunction@intarray_float_charptrと、widgetライブラリは公開されているだけになるfunctionため、問題が発生します。

ただし、次のように含める場合:

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

functionコンパイラは、マングルされていないバージョンのを使用する必要があることを認識します。

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

#ifdef __cplusplus
    extern "C" {
#endif

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

#ifdef __cplusplus
    }
#endif

Cコンパイラを使用してこれを含めると、#ifdef行によってextern "C"内容が消えます。C++ コンパイラ ( where__cplusplusが定義されている) の場合、すべてがマングルされません。

于 2011-11-03T14:05:09.550 に答える
4

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つのオブジェクトファイルのうちf、C ++のマングル名でわかるのは1つだけです)。

おそらく、これを修正する最もクリーンな方法は、ヘッダーファイルをCとC++の両方と互換性を持たせることです。

module.h

#ifdef __cplusplus
  extern "C" {
#endif

int f(int arg);

#ifdef __cplusplus
  }
#endif
于 2011-11-03T14:11:21.280 に答える
4

extern "C"ライブラリから関数をエクスポートするときの の非常に一般的な使用方法の 1 つです。C++ の名前マングリングを無効にしないと、ライブラリのクライアントが関数に名前を付けるのが非常に難しくなる可能性があります。逆にCリンケージでエクスポートした関数をインポートする場合も同様です。

于 2011-11-03T14:04:02.067 に答える
1

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

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

C ++は、BがAの呼び出し方法を知っているようなバイナリレイアウトを記述していません。通常、この問題は、同じコンパイラを使用してAとBを生成することで回避されます。より一般的なソリューションが必要な場合は、externキーワードを使用します。これにより、関数がC方式で公開されます。Cは、さまざまなコンパイラのさまざまなバイナリが相互に通信できるように、バイナリ形式を記述します。

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

于 2011-11-03T14:10:43.760 に答える
1

C ++コード内#includeで、外部ライブラリ(Cでコード化)のヘッダーがあり、そこにある関数が宣言されていないextern "C"場合、それらは機能しません(リンク時に未定義の参照を取得します)。

しかし、最近では、Cライブラリをコーディングしてヘッダーファイルを提供する人々はそれを知っている傾向があり、多くの場合extern "C"、ヘッダーファイルに(適切に保護された#ifdef __cplusplus)を配置します。

おそらく、理解するためのより良い方法は、(Linuxシステムを使用していると仮定して)nmユーティリティを使用して、ライブラリまたは実行可能ファイルで使用されている(マングルされていない)名前を表示することです。

于 2011-11-03T14:11:02.240 に答える
1

C で記述されたライブラリとリンクするexternと、リンカーが関数を見つけられるように名前を装飾しないようにコンパイラに指示します。C++ では、関数名などにリンカの情報 (名前に含まれる引数の型やサイズなど) があります。

于 2011-11-03T14:05:58.193 に答える