言語リンケージ
異なるプログラミング言語で書かれたモジュール間のリンク機構を提供します。
extern string-literal { declaration-seq(オプション) }
|
(1) | ||||||||
extern string-literal declaration
|
(2) | ||||||||
string-literal | - | 要求される言語リンケージの名前。 |
declaration-seq | - | 宣言の並び。 ネストした言語指定を含んでも構いません。 |
declaration | - | 宣言。 |
目次 |
[編集] 説明
すべての関数型、外部リンケージを持つすべての関数名、外部リンケージを持つすべての変数名は、言語リンケージと呼ばれる性質を持ちます。 言語リンケージは別のプログラミング言語で書かれたモジュールとリンクするために必要な要件の集合 (呼び出し規約、名前修飾のアルゴリズム、など) をカプセル化します。
サポートされていることが保証されている言語リンケージは2つだけです。
extern "C" { int open(const char *pathname, int flags); // C の関数の宣言。 } int main() { int fd = open("test.txt", 0); // C++ のプログラムから C の関数を呼びます。 } // この C++ の関数は C のコードから呼べます。 extern "C" void handler(int) { std::cout << "Callback invoked\n"; // C++ を使用できます。 }
言語リンケージはすべての関数型の一部です。 関数ポインタも同様に言語リンケージを保持します。 関数型の言語リンケージ (呼び出し規約を表します) および関数名の言語リンケージ (名前修飾を表します) はお互いに独立しています。
extern "C" void f1(void(*pf)()); // 引数を取らず void を返す C の関数 // へのポインタを取って void を返す // C リンケージの関数 f1 を宣言します。 extern "C" typedef void FUNC(); // 引数を取らず void を返す C の関数型 // として FUNC を宣言します。 FUNC f2; // 名前 f2 は C++ リンケージを持ちますが、その型は C の関数です。 extern "C" FUNC f3; // 名前 f3 は C リンケージを持ち、その型は C の関数 void() です。 void (*pf2)(FUNC*); // 名前 pf2 は C++ リンケージを持ち、その型は // 「『引数を取らず void を返す C の関数へのポインタ』型の引数 // を1個取り void を返す C++ の関数へのポインタ」です。 extern "C" { static void f4(); // 関数 f4 の名前は内部リンケージ (言語なし) を持ちますが、 // その関数の型は C 言語リンケージを持ちます。 }
同じ名前空間で同じ名前かつ同じ引数リストを持つ2つの関数が2つの異なる言語リンケージを持つことはできません (しかし、std::qsort や std::bsearch の場合のように、引数のリンケージはそのようなオーバーロードを許しても良いことに注意してください)。 同様に、同じ名前空間で2つの変数が2つの異なる言語リンケージを持つことはできません。
[編集] 「C」リンケージに対する特別なルール
[編集] ノート
言語指定は名前空間スコープにのみ現れることができます。
言語指定の波括弧はスコープを確立しません。
言語指定がネストしたときは、最も内側の指定が有効になります。
関数は、言語指定付きで宣言された後、言語指定なしで再宣言でき、2回目の宣言では1回目の言語指定が再使用されます。 逆は真ではありません。 最初の宣言が言語リンケージを持たない場合、それは "C++" とみなされ、別の言語での再宣言はエラーになります。
言語リンケージ指定内に直接含まれる宣言は、宣言される名前のリンケージおよびそれが定義かどうかを決定する目的に対して、 extern 指定子を持っているかのように扱われます。
extern "C" int x; // 宣言ですが定義ではありません。 // 上の行は extern "C" { extern int x; } と同等です。 extern "C" { int x; } // 宣言かつ定義です。
extern "C"
は C のライブラリ関数の宣言を含むヘッダファイルを C++ プログラムでインクルードすることを可能としますが、同じヘッダファイルを C のプログラムと共有する場合、 extern "C"
(C では使用できません) は適切な
#ifdef (一般的には __cplusplus) で隠蔽しなければなりません。
#ifdef __cplusplus extern "C" int foo(int, int); // C++ コンパイラはこちらを見ます。 #else int foo(int, int); // C コンパイラはこちらを見ます。 #endif
[編集] 参考文献
- C++14 standard (ISO/IEC 14882:2014):
- 7.5 Linkage specifications [dcl.link]
- C++11 standard (ISO/IEC 14882:2011):
- 7.5 Linkage specifications [dcl.link]