22

静的メンバー関数と extern "C" リンケージ関数の違いは何ですか? たとえば、C++ で「makecontext」を使用する場合、関数へのポインターを渡す必要があります。「makecontext」はCであるため、Googleはextern「C」リンケージを使用することをお勧めします。しかし、静的を使用しても同様に機能することがわかりました。私は運がいいのか、それとも…

class X {
   public:
   static void proxy(int i) {}
}
makecontext(..., (void (*)(void)) X::proxy, ...);

extern "C" void proxy(int i) {}
makecontext(..., (void (*)(void)) proxy, ...);

EDIT:静的メンバーバージョンが機能しないコンパイラまたはアーキテクチャを表示できますか(コンパイラのバグではありません)?

4

5 に答える 5

33

はい、あなたは幸運です:) extern "C"は、デフォルトであるextern "C ++"の他に、すべてのC++コンパイラがサポートしなければならないC言語の1つの言語リンケージです。コンパイラは他の言語リンケージをサポートする場合があります。たとえば、GCCは、Javaコードとのインターフェースを可能にするextern "Java"をサポートしています(これは非常に面倒ですが)。

extern "C"は、関数がCコードで呼び出し可能であることをコンパイラーに通知します。これには、実装に応じて、適切な呼び出し規約と適切なC言語名のマングリング(「装飾」と呼ばれることもあります)を含めることができますが、必須ではありません。静的メンバー関数がある場合、その呼び出し規約はC++コンパイラーの1つです。多くの場合、それらはそのプラットフォームのCコンパイラーと同じです-だから私はあなたがただ幸運だと言いました。C APIがあり、関数ポインターを渡す場合は、常にextern"C"で宣言された関数にCAPIを配置することをお勧めします。

extern "C" void foo() { ... }

関数ポインタ型にはリンケージ仕様が含まれていませんが、次のようになります。

void(*)(void)

リンケージは型の不可欠な部分です-typedefなしで直接表現することはできません:

extern "C" typedef void(*extern_c_funptr_t)();

厳密モードのComeauC++コンパイラは、たとえば、上記のextern "C"関数のアドレスをに割り当てようとすると、エラーを(void(*)())出力します。これは、C++リンケージを持つ関数へのポインタであるためです。

于 2009-02-26T20:06:24.913 に答える
5

これextern Cは、C/C++ 相互運用性の推奨される方法です。ここでマスターの話です。eduffy の回答に追加するには: グローバル名前空間の静的関数と変数は非推奨であることに注意してください。少なくとも匿名の名前空間を使用してください。

に戻るextern C: extern C を使用しない場合は、正確なマングル名を知って使用する必要があります。それははるかに苦痛です。

于 2009-02-26T20:07:09.263 に答える
4

extern "C"C ++コンパイラの名前マングリング(オーバーロードに必要)を無効にします。

A.cppで関数をであると宣言すると、B.cppではその関数を見つけるstaticことができません(Cから残ったものであり、匿名の名前空間内に関数を配置するのと同じ効果があります)。

于 2009-02-26T20:02:33.597 に答える