最終更新:2026-10-12
C++ extern リンケージ指定¶
著者について:¶
個人公式アカウント:

1.C++とCのコンパイルの違い¶
C++ではヘッダファイルでextern "C"と修飾された関数をよく見かけますが、何の役割があるのでしょうか? C言語モジュールで定義された関数をC++からリンクするためのものです。
C++はCと互換性がありますが、C++ファイルの関数をコンパイルして生成されるシンボルは、C言語が生成するものと異なります。C++は関数のオーバーロードをサポートしており、C++の関数をコンパイルして生成されるシンボルには関数の引数型の情報が含まれますが、Cには含まれません。
例えばint add(int a, int b)関数をC++コンパイラで.oファイルに生成すると、addはadd_int_intのような形になり、Cなら_addのようになります。つまり、同じ関数でもCとC++では、コンパイル後に生成されるシンボルが異なるのです。
これがある問題を引き起こします:C++の中でC言語で実装された関数を使うと、コンパイル・リンクのときにエラーになり、対応するシンボルが見つからないと示されます。ここでextern "C"が役に立ちます:リンカに、C++で修飾されたシンボルではなく、_addのようなC言語のシンボルを探すよう伝えるのです。
2.C++からC関数を呼ぶ¶
C++がC関数を呼ぶ例:Cのヘッダファイルを読み込むときは、extern "C"を追加する必要があります
//add.h
#ifndef ADD_H
#define ADD_H
int add(int x,int y);
#endif
//add.c
#include "add.h"
int add(int x,int y) {
return x+y;
}
//add.cpp
#include <iostream>
#include "add.h"
using namespace std;
int main() {
add(2,3);
return 0;
}
コンパイル:
リンク:
extern "C"を追加していない場合のエラー:
> g++ add.cpp add.o -o main
add.o:在函数‘main’中:
add.cpp:(.text+0x0): `main'被多次定义
/tmp/ccH65yQF.o:add.cpp:(.text+0x0):第一次在此定义
/tmp/ccH65yQF.o:在函数‘main’中:
add.cpp:(.text+0xf):对‘add(int, int)’未定义的引用
add.o:在函数‘main’中:
add.cpp:(.text+0xf):对‘add(int, int)’未定义的引用
collect2: error: ld returned 1 exit status
extern "C"を追加した後:
add.cpp
#include <iostream>
using namespace std;
extern "C" {
#include "add.h"
}
int main() {
std::cout << add(2, 3) << std::endl;
return 0;
}
コンパイルするときは、必ず先にgccで中間ファイルadd.oを生成します。
そしてコンパイル:
bazelでコンパイルする場合は、実行します:bazel run basic_content/extern/extern_c++:main
また、通常Cコードを汎用的に、すなわちCからもC++からも呼べるようにするため、ヘッダファイルは通常次のように書かれます:
すなわち、C++がこのインターフェースを呼ぶとき、Cインターフェースの方式で呼ばれます。この方式により、C++側は追加のextern Cが不要になります。標準ライブラリのヘッダファイルも通常は同様のやり方です。そうでなければ、なぜあなたはextern Cなしでstdio.hのC関数を直接使えるのでしょうか?
上記の例のソースコードはこちら:
2.CからC++関数を呼ぶ¶
extern "C"はCの中では文法エラーとなるため、C++のヘッダファイルに置く必要があります。
// add.h
#ifndef ADD_H
#define ADD_H
extern "C" {
int add(int x,int y);
}
#endif
// add.cpp
#include "add.h"
int add(int x,int y) {
return x+y;
}
// add.c
extern int add(int x,int y);
int main() {
add(2,3);
return 0;
}
コンパイル:
リンク:
上記の例のソースコードはこちら:
以上より、使用方法をまとめます。C言語のヘッダファイルの中では、その外部関数に指定できるのはextern型だけであり、C言語はextern "C"宣言をサポートしません。.cファイルにextern "C"が含まれていると、コンパイルの文法エラーになります。したがってextern "C"の使用は、すべてcppプログラムの関連ファイルまたはそのヘッダファイルに置きます。
次のような形式がまとめられます:
(1)C++がC関数を呼ぶ:
(2)CがC++関数を呼ぶ
ただし、C++がCインターフェースを呼ぶ場合と異なり、C++はコンパイル済みのC関数を本当に呼び出せますが、ここでのCからC++を呼ぶのは、C++のコードをCコードとしてコンパイルしてから呼んでいるにすぎません。つまり、CはC++のライブラリ関数を直接呼び出すことはできないのです。
関連トピック¶
- C++ 純粋仮想関数と抽象クラス | C++那些事
- C++ assert アサーション | C++那些事
- C++ ビットフィールド | C++那些事
- C 言語による C++ 多態の実現 | C++那些事
- C++ const 定数と修飾 | C++那些事
- C++ const ファミリー | C++那些事
- C++ 間接参照演算子 * | C++那些事
- C++ 初期化と代入 | C++那些事
- C++ 複数戻り値の書き方 | C++那些事
- C++ mutable キーワード | C++那些事