40

C プログラムから呼び出す必要がある C++ 関数を作成しました。Cから呼び出せるようにするためextern "C"に、関数宣言に を指定しました。次に、C++ コードをコンパイルしましたが、コンパイラ (Dignus Systems/C++) が関数のマングル名を生成しました。したがって、どうやらextern "C".

これを解決するためextern "C"に、関数定義に を追加しました。この後、コンパイラは C から呼び出し可能な関数名を生成しました。

技術的にはextern "C"、関数宣言でのみ指定する必要があります。これは正しいですか?( C++ FAQにこれの良い例があります。) 関数定義でも指定する必要がありますか?

これを示す例を次に示します。

/* ---------- */
/* "foo.h"    */
/* ---------- */

#ifdef __cplusplus
extern "C" {
#endif

/* Function declaration */
void foo(int);

#ifdef __cplusplus
}
#endif

/* ---------- */
/* "foo.cpp"  */
/* ---------- */

#include "foo.h"

/* Function definition */
extern "C"               // <---- Is this needed?
void foo(int i) {
  // do something...
}

私の問題は、何かを誤ってコーディングした結果である可能性があります。または、コンパイラのバグを見つけた可能性があります。いずれにせよ、stackoverflow に相談して、技術的にどちらが「正しい」方法であるかを確認したかったのです。

4

6 に答える 6

40

' extern "C"' は、宣言に含まれていて、定義のコンパイルで既に確認されている限り、関数定義で必要としないでください。この規格では、具体的に次のように述べられています (7.5/5 リンケージ仕様)。

関数は、明示的なリンケージ指定が見られた後、リンケージ指定なしで宣言できます。前の宣言で明示的に指定されたリンケージは、そのような関数宣言の影響を受けません。

extern "C"ただし、実際には extern "C" リンケージを持つ関数であるため、通常は定義にも ' ' を付けます。多くの人は、不必要で冗長なものが宣言に含まれていることを嫌います (virtualメソッドのオーバーライドを行うなど) が、私はその 1 人ではありません。

于 2009-09-04T18:48:59.310 に答える
1

私はちょうど同様の問題を抱えていて、これを頭の中で明確にするのに時間がかかったので、ここで明確にする必要があると思います.Brooks Mosesだけがこれに適切に触れました.. .

要約すると、ヘッダーはあなたを怒らせるかもしれません.コンパイラが見るのはcppファイルだけです.ヘッダーがextern "C"と共にcppに含まれていない場合(私はよく見ます)、extern "C"はCXXコンパイラがCリンケージでそれを作成することを知ることができるように、cppファイルのどこかに(定義または別の宣言のいずれか)、コンパイラはヘッダーを気にせず、リンカーのみを気にします。

于 2015-01-21T04:04:03.273 に答える
0

それは両方の周りにあるはずです。コンパイラは、呼び出しサイト (宣言のみが表示される場合があります) をコンパイルするときに C シンボル名と呼び出し規則を使用することを認識する必要があります。関数定義自体 (他の宣言は表示されない場合があります)。

さて、定義が存在する翻訳単位から見える extern-C 宣言がある場合、定義から extern-C を除外することで回避できるかもしれませんが、それは確かではありません.

于 2009-09-04T18:32:30.560 に答える