web-dev-qa-db-ja.com

C ++でextern "C"を使用する場合

可能性のある複製:
なぜC++でextern“ C” {#include <foo.h>}が必要なのですか?

私はしばしば次のようにコーディングされたプログラムを見てきました:

extern "C" bool doSomeWork() {
  //
  return true;
}

なぜextern "C"ブロックを使用するのですか?これをC++の何かで置き換えることはできますか? extern "C"を使用する利点はありますか?

this を説明するリンクが表示されますが、すでにC++があるのに、なぜCでコンパイルする必要があるのですか?

22
pankajt

extern "C"は名前をマングルしないようにします。

次の場合に使用されます。

  1. C++でCライブラリを使用する必要があります

    extern "C" int foo(int);
    
  2. いくつかのC++コードをCにエクスポートする必要があります

    extern "C" int foo(int) { something; }
    
  3. 共有ライブラリのシンボルを解決する機能が必要です-したがって、マングリングを取り除く必要があります

    extern "C" int foo(int) { something; }
    ///
    typedef int (*foo_type)(int);
    foo_type f = (foo_type)dlsym(handle,"foo")
    
32
Artyom

Extern "C"が意味を成す1つの場所は、Cコードとしてコンパイルされたライブラリにリンクする場合です。

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

そうしないと、ライブラリにCリンケージ(_myfunc)を持つ関数が含まれているためにリンカーエラーが発生する可能性がありますが、ライブラリのヘッダーをC++コードとして処理するC++コンパイラーが関数のC++シンボル名を生成しました( "_myfunc @ XAZZYE"-これはマングリングと呼ばれ、コンパイラごとに異なります)。

Extern "C"が使用される別の場所は、C++で記述された関数でもCリンケージを保証することです。

extern "C" void __stdcall PrintHello() {
  cout << "Hello World" << endl;
}

そのような関数は、DLLにエクスポートできます。コンパイルするとその名前がマングルされないため、他のプログラミング言語から呼び出すことができます。同じ関数の別のオーバーロードを追加した場合、たとえば、.

extern "C" void __stdcall PrintHello() {
  cout << "Hello World" << endl;
}
extern "C" void __stdcall PrintHello(const char *name) {
  cout << "Hello, " << name << endl;
}

ほとんどのコンパイラはこれをキャッチし、DLLパブリック関数で関数のオーバーロードを使用できなくなります。

14
Cygon