7

C プログラムで使用する C++ 共有ライブラリを作成しています。しかし、 と について質問がexternありextern "C"ます。

次のコードを検討してください

私のヘッダーファイルは次のようなものです:

#ifdef __cplusplus      
     extern "C" int global;
     extern "C" int addnumbers(int a, int b); 
 #else
      extern int global;
 #endif

これは問題なく動作します。宣言するしかない

int global;

私の.cppまたは私の.cファイルのいずれかで。ただし、私が理解していないのは次のとおりです。

extern "C"とここはどう違いexternますか?コメントアウトしてみましたがextern "C" int global、うまくいきました!なんで?

私はそれextern "C"がCリンケージを作るために使われていることを知っています。それが私が持っている理由ですextern "C" int addnumbers(int,int)。つまり、C プログラムで使用する C++ 関数を書きたい場合は、extern "C". さて、グローバル変数についてはどうですか - ここでは状況が違うと思いますか? C プログラムで という名前の C++ 変数を使用したいのですが、global使用できexternませんextern "C"。何故ですか?これは私には直感的ではありません。

コメント: 変数と関数に使用する場合の違いを尋ねているので、これは重複しているとは思いません。

4

4 に答える 4

16

C++ 宣言 (オブジェクトと関数の両方)にアタッチextern "C"することで、それらに「C リンケージ」を与え、C コードからアクセスできるようにします。この「言語リンケージ」指定を省略すると、コンパイラーは適切なリンケージを行う努力をしません。関数の場合、マングリングが原因でリンクが失敗します。グローバル変数の場合、変数はマングリングを必要としないため、すべてが正常に機能する可能性があります。

extern "C"しかし、私のシステム (MS Visual Studio) では、C++ ヘッダー ファイルでリンケージ仕様を指定するのを「忘れる」と、C と C++ の間のリンケージが機能しません。エラー メッセージの例:

error LNK2001: unresolved external symbol "int global" (?_global)

global一方、dumpbinユーティリティでの定義を含むコンパイル済みの C++ ソース コードを調べると、

00B 00000014 SECT4  notype       External     | ?global@@3HA (int global)

そのため、MS Visual Studio は、C リンケージがない限り、グローバル変数の名前をマングルします。これにより、C リンケージ仕様が必須になります。


さらに、次の例を検討してください。

namespace example {
    int global;
}

グローバル変数が名前空間内にある場合、C コードはそれにアクセスできません。この場合、すべてのコンパイラは、C++ 宣言で適切なリンケージ仕様を必要とします。

namespace example {
    extern "C" int global;
}

結論:

Cリンケージが必要な場合に使用extern "C"します-それが関数かグローバル変数かは関係ありません。グローバル変数の場合は、関係なく動作する可能性がありますが、保証されていません (危険な場合があります)。

于 2016-07-05T16:48:32.693 に答える
1

extern次の変数 (global) がまだ宣言されていない可能性があることをコンパイラに伝えるだけですが、別の翻訳単位でグローバルとして宣言されており、リンク段階でシンボル「global」がメモリ内の領域に関連付けられます。

extern "C"一部の人がコメントしたように、C++ での名前マングリングの問題を解決するために使用されますが、この関数はリンカーによって (または同様のものとして) 知られますが、addnumbers_i_ic ではそのシンボルはaddnumbers

于 2016-07-05T15:05:36.563 に答える
0

「C++ には、C バインディングを持つ関数を宣言するための特別なキーワードがあります: extern "C"。 extern "C" として宣言された関数は、C 関数と同様に、関数名をシンボル名として使用します。そのため、非メンバー関数のみextern "C" として宣言でき、オーバーロードできません。」

C++ には、コンパイラによって生成される関数名の標準はありません。キーワード extern "C" は、C 標準で関数名を生成するようにコンパイラに指示します。

于 2016-07-01T11:10:28.940 に答える