extern "C"
というコードを最近良く見かけるので少し調べてみた。
簡単にいうとこれはCとC++のソースを混在させてコンパイルするときのいわゆるマングリングを解決するための表現だ。
What is Mangling?
マングリングとは、C++のソースをコンパイルしたときにできるオブジェクトファイルの中のシンボルにいろいろ変なものがつくことをいう。
例えば以下のようなC++のソースがあったとする。
#include <iostream>
int add(int a, int b){
return a+b;
}
int main(void){
std::cout << add(1,2) << std::endl;
return 0;
}
これをコンパイルした実行ファイルの中身をnm
で見るとこんな感じになっている。
0000000100000d00 T __Z3addii
// 省略
0000000100000d50 T _main
// 省略
add関数とmain関数を定義したのでその2つのシンボルができる。このときmainはあまり変な感じになっていないのに、addはなんだかごちゃっとしたものが付いている。これはC++では関数のオーバロードや名前空間の概念があるため、同じ関数名でもシンボルを分ける必要があるからだ。
ところがCではこんなことしないので、Cのコンパイラは_add
というシンボルを探してしまう。そこでextern "C"
が役に立つ。
addの関数宣言の際にヘッダファイルとして
extern "C" int add(int, int);
とやるとなんとマングリングを行わずにシンボルを作成してくれる。
C,C++が混在しているような場合に効果を発揮する宣言なのです。