関数とヘッダファイルを含むextern「C」の役割


よくcppのコードの中でこのようなコードを見ます: #ifdef __cplusplus
extern "C" {
#endif

//

#ifdef __cplusplus
}
#endif
このようなコードはいったいどういう意味ですか?まず、_cplusplusはcppのカスタムマクロであり、このマクロを定義するとcppのコードであることを示す.すなわち、上記のコードの意味は、これがcppのコードである場合、extern「C」{と}を加えてコードを処理することである.extern「C」の使用理由を理解するには,cppにおける関数のリロード処理から始めなければならない.c++では、リロードメカニズムをサポートするために、コンパイル生成の符号化では、関数の戻りタイプなど、関数の名前をいくつか処理する.Cでは、単純な関数名にすぎず、他の情報は入れない.すなわち、C++とC対で生成する関数名の処理は異なる.たとえば、次の簡単な関数では、extern「C」を追加するかどうかで生成されるアセンブリコードにどのような変化があるかを見てみましょう. int f(void)
{
return 1;
}
extern「C」を追加するときに生成されるアセンブリコードは、 .file "test.cxx"
.text
.align 2
.globl _f
.def _f; .scl 2; .type 32; .endef
_f:
pushl %ebp
movl %esp, %ebp
movl $1, %eax
popl %ebp
ret
ですが、extern「C」を追加しない後の .file "test.cxx"
.text
.align 2
.globl __Z1fv
.def __Z1fv; .scl 2; .type 32; .endef
__Z1fv:
pushl %ebp
movl %esp, %ebp
movl $1, %eax
popl %ebp
ret
の2つのアセンブリコードもgcc-Sコマンドを使用して生成されます.すべての場所は同じで、発生した関数名だけで、一つは_f,一つは_Z1fv. extern「C」を追加するかどうかが関数名に与える影響を理解し、なぜextern「C」を使用する必要があるのかについて議論を続けます.C++の親がC++を設計する際には、当時すでに大量のCコードが存在していたことを考慮し、元のCコードをサポートし、Cライブラリを書き上げるためには、C++でできるだけCをサポートする必要があり、extern「C」はその戦略の一つである.このような状況を考えてみてください.1つのライブラリファイルはすでにCで書かれていて、よく実行されています.このとき、私たちはこのライブラリファイルを使用する必要がありますが、C++を使用してこの新しいコードを書く必要があります.このコードがC++方式でこのCライブラリファイルをリンクすると、リンクエラーが発生する.まず、Cの処理方式を用いて関数を書きます.つまり、この関数が当時Cで書かれたと仮定します. //f1.c
extern "C"
{
void f1()
{
return;
}
}
のコンパイルコマンドはgcc-c f 1です.c -o f1.o f 1というものが生まれた.oのライブラリファイル.このf 1関数を呼び出すコードをもう1段書きます: // test.cxx
// extern f1 ,
// ,
// .
extern void f1();

int main()
{
f1();

return 0;
}
gcc-c testを通ります.cxx -o test.o testという名前のoのファイル.それからgcc testを使います.o f1.oは2つのファイルをリンクしますが、エラーが発生しました.エラーのヒントは: test.o(.text + 0x1f):test.cxx: undefine reference to 'f1()' 、つまりtestをコンパイルしています.cxxの場合、コンパイラはC++でf 1()関数を処理しますが、実際にリンクされたライブラリファイルはCで関数を処理しているので、リンクが通れないエラーが発生します.リンクが関数を見つけられないからです.したがって、C++コードでCで書かれたライブラリファイルを呼び出すには、extern「C」でコンパイラにCで書かれたライブラリファイルであることを伝える必要があります.Cでリンクしてください.例えば、今、私たちはCライブラリファイルを持っています.そのヘッダファイルはf.hで、生成されたlibファイルはf.libです.では、C++でこのライブラリファイルを使用するには、 extern "C"
{
#include "f.h"
}
が上の問題に戻り、リンクエラーを修正するには、testをこのように書き換える必要があります.cxx: extern "C"
{
extern void f1();
}

int main()
{
f1();

return 0;
}
再コンパイルしてリンクすればよい.CとC++の関数に対する処理方式が異なることをまとめる.extern"C"はC++がCで書かれたライブラリファイルを呼び出すことができる手段であり,コンパイラにCを用いて関数を処理するように提示する場合はextern"C"を用いて説明する.