34

C と C++ の違いを理解していないかもしれませんが、いつ、なぜ使用する必要があるのでしょうか。

extern "C" {

? どうやらそれは「リンケージ規約」です。

私はそれについて簡単に読んで、MSVS に含まれるすべての .h ヘッダー ファイルがコードを囲んでいることに気付きました。「C++コード」ではなく「Cコード」とは正確にはどのタイプのコードですか? C++ にはすべての C コードが含まれていると思いましたか?

これは事実ではなく、C++ は異なり、標準機能/関数はどちらか一方に存在するが両方には存在しない (つまり、printf は C で cout は C++) と推測していますが、C++ は後方互換性がありますが、 extern "C" 宣言。これは正しいです?

私の次の質問は最初の回答によって異なりますが、とにかくここで質問します: C で記述された MSVS ヘッダー ファイルは extern "C" { ... } で囲まれているため、いつこれを使用する必要がありますか?あなた自身のコードであなた自身?コードが C コードであり、C++ コンパイラでコンパイルしようとしている場合、問題なく動作するはずです。なぜなら、含めるすべての標準 h ファイルには、C++ コンパイラで extern "C" が既に含まれているからです。

C++ でコンパイルするときにこれを使用する必要がありますが、既にビルドされている C ライブラリなどにリンクしますか?

4

7 に答える 7

37

extern "C"C で実装/コンパイルされた関数を宣言するときは、C++ で使用する必要があります。 を使用するextern "C"と、コンパイラ/リンカーに、C++ の名前マングリングと C++ の呼び出し規則の代わりに、C の命名規則と呼び出し規則を使用するように指示されます。 . extern "C"他のライブラリによって提供される関数については、C と C++ の両方にエクスポートする公開 API のために、適切に作成されたライブラリが既にこれを持っているため、を使用する必要はほとんどありません。ただし、C と C++ の両方で使用できるようにするライブラリを作成する場合は、条件付きでそれをヘッダーに配置する必要があります。

すべての C コードが C++ コードであるかどうかについては、そうではありません。C++ は「C のスーパーセット」であるというのはよくある誤解です。C++ は確かに C との互換性を可能な限り保つよう努めていますが、いくつかの非互換性があります。たとえば、boolは有効な C++ ですが有効な C ではありませんが、 _Boolは C99 に存在しますが、C++ では使用できません。

システムの「.h」ファイルでextern「C」を使用する必要があるかどうかについては....適切に設計された実装にはそれらが含まれているため、それらを使用する必要はありません。ただし、それらが確実に提供されるようにするには、「c」で始まり「.h」を省略した同等のヘッダー ファイルを含める必要があります。たとえば、<ctype.h> をインクルードすると、ほぼすべての適切なシステムに extern "C" が追加されます。ただし、C++ 互換のヘッダーを保証するには、代わりにヘッダー <cctype> を含める必要があります。

C++ FAQ Lite の Mixing C and C++にも興味があるかもしれません。

于 2010-05-09T06:14:34.673 に答える
21

他の答えは正しいですが、完全な「ボイラープレート」の例がおそらく役立つでしょう。C および/または C++ プロジェクトに C コードを含める標準的な方法は次のとおりです。

//
// C_library.h
//

#ifdef __cplusplus
extern "C" {
#endif

//
// ... prototypes for C_library go here ...
//

#ifdef __cplusplus
}
#endif

-

//
// C_library.c
//

#include "C_library.h"

//
// ... implementations for C_library go here ...
//

-

//
// C++_code.cpp
//

#include "C_library.h"
#include "C++_code.h"

//
// ... C++_code implementation here may call C functions in C_library.c ...
//

注: 上記は、Objective-C++ からの C コードの呼び出しにも適用されます。

于 2010-05-09T06:58:11.930 に答える
16

C++ コンパイラは、C コンパイラとは異なる方法で、シンボル テーブル内の名前をマングルします。extern "C"宣言を使用して、シンボル テーブルを作成するときに代わりに C マングリング規則を使用するように C++ コンパイラに指示する必要があります。

于 2010-05-09T06:13:16.113 に答える
3

「extern c」を使用して、C++ dll 関数をエクスポートするときに行われる余分な名前マングリングを把握しなくても、C# が C++ コードを読み取れるようにします。それ以外の場合は、DLL 内の C++ 関数に適切にアクセスするために、C# 側の関数エントリ ポイントの最後に追加しなければならない余分な無意味な (または実際には英語以外の) 文字があります。

于 2010-05-09T06:24:52.577 に答える
3

extern "C" {}ブロックは、C の命名規則と呼び出し規則を使用するように C++ コンパイラに指示します。これを使用しない場合、C++ プロジェクトに C ライブラリを含めようとすると、リンカー エラーが発生します。これは、C++ が名前を台無しにするためです。C++ プロジェクトで使用される場合に備えて、すべての C ヘッダーでこれを使用する傾向があります。

#ifdef __cplusplus
extern "C" {
#endif

/* My library header */

#ifdef __cplusplus
} // extern
#endif
于 2010-05-09T06:25:58.837 に答える
2

extern "C"C++ コンパイラでコンパイルされたコードで C 呼び出し規約を使用する場合に使用する必要があります。これには 2 つの理由があります。

  • C で実装された関数があり、C++ から呼び出したいとします。

  • C++ で実装された関数があり、それを C から呼び出したいとします。この場合、関数インターフェイスで使用できるのは C++ の C 部分のみであることに注意してください (クラスなどは使用できません)。

C とは別に、これは、C++ と、C と同じ呼び出しおよび命名規則を使用する他の言語との間で相互運用する場合にも適用されます。

通常、C ヘッダー ファイル内の宣言は、

#ifdef __cplusplus
extern "C" {
#endif

[... C declarations ...]

#ifdef __cplusplus
}
#endif

C++ から使用できるようにします。

于 2010-05-09T06:37:22.330 に答える
1

C++ 関数は名前マングリングの影響を受けます。これにより、 を使用しない限り、C コードから直接呼び出すことができなくなりますextern "C"

于 2010-05-09T06:12:45.160 に答える