場合によっては、C プログラムの下で C++ ライブラリを呼び出す必要があります。多くの記事を読んでも、言葉が深すぎて冗長すぎて一度に理解できないか、例が単純すぎて理解できないか使用できないかのどちらかです。両者の折衷案をとり、シンプルで分かりやすい説明と例を示します。
まず、C と C++ では関数をコンパイルした後に生成される関数名が異なるため、両者を共通に使用することはできません。また、C プログラムでコンパイルしたダイナミック ライブラリを C++ で呼び出すこともできず、その逆も可能です。その逆も。では、C はどのようにして C++ を呼び出すのでしょうか? このインターフェイス プログラムのinterface.cpp
ファイルは、 C++ ライブラリの特定の関数を C 関数にカプセル化する役割を果たし、ヘッダ ファイルはinterface.h
main 関数によって呼び出されます。例を見るのが最も簡単ですので、見てみましょう。
まず、C++ プログラムがありtest.cpp
、test.hpp
// test.hpp 文件内容:定义了ClassA类
class ClassA{
public:
void func(int a);
};
// test.cpp 文件内容:实现了ClassA::func(int a)函数
#include <iostream>
#include "test.hpp"
using namespace std;
void ClassA::func(int a){
cout<<"class A: "<<a<<endl;
}
これがすでにある C++ プログラムであると仮定すると、main.c
C プログラムでそれを呼び出すにはどうすればよいでしょうか? 答えは、インターフェースを書くことですinterface
。
// interface.h文件内容
#ifdef __cplusplus
extern "C"{
#endif
void func(int a);
#ifdef __cplusplus
}
#endif
// interface.cpp 文件内容
#include "test.hpp"
#include "interface.h"
void func(int a){
ClassA c;
c.func(a);
}
上記はC++ ライブラリと C プログラムを繋ぐブリッジです。interface.h
ここでextern "C"{}
囲まれた部分はC プログラムをコンパイルすることを意味します。extern "C"{}
マクロが定義されたときにステートメントが有効になり__cplusplus
、 g++ が使用されるとこのマクロが自動的にコンパイルされます。 が定義されます。C言語でコンパイルするとマクロは定義されず__cplusplus
、当然有効にはなりませんextern "C"{}
(C言語では認識しないextern "C"{}
のでマクロで切り替える必要があります)。Interface.cpp
プログラムではtest.cpp
、C++ 関数は main で呼び出すための C スタイル関数としてカプセル化されています。
Interface
ここで、実装ファイルは.cpp
、ヘッダー ファイルは であることがわかります.h
。これらは、C プログラムが.cpp
C++ ライブラリをリンクするために使用されます.h
。これを読むと非常に混乱しますが、とりあえず概要は理解でき、main 関数について話すときに戻って理解することができます。この時点で、C++ ライブラリとインターフェイスをlibtest.so
動的ライブラリに共同コンパイルできます。
g++ test.cpp interface.cpp -shared -fPIC -o libtest.so
最終的に次のように main 関数に到達しました
// main.c 文件内容
#include "interface.h"
int main()
{
func(1);
}
次に、次のように main 関数をコンパイルする必要があります。
gcc main.c ./libtest.so -o main
つまり、C 言語プログラムは C++ プログラム ライブラリを呼び出します。要約すると、パッケージ インターフェイスを作成することです。インターフェイスの特定の実装 cpp ファイルは、C++ ライブラリを C プログラムの読み取り可能なインターフェイスにパッケージ化するために使用されます。インターフェイスのヘッダー ファイル .h は、 C プログラムによって呼び出されます。そうなると読者は、なぜinterface.hに__cplusplus
マクロ定義制御スイッチを追加する必要がないのか疑問に思うでしょうextern "C"
。これは、interface.h が と によって同時に呼び出されるためでありinterface.cpp
、main.c
前者は C++ モードでコンパイルする必要があり、後者は C モードでコンパイルする必要があり、これにはスイッチが必要です。
他のチュートリアルを探す必要はありません。このブログは、 を理解するのに最も役立つ可能性が高いextern "C"
記事です。何度か読んで手動で実装すると、理解できるようになります。
備考:
1. gcc と g++ の違いは、前者が C プログラムのコンパイルに使用され、後者が C++ プログラムのコンパイルに使用されるということではなく、簡単なプログラムであれば.cpp
gcc を使用してコンパイルすることもできます。g++ のカーネルは gcc のままですが、いくつかのマクロ定義とライブラリがデフォルトで追加されます。つまり、gcc を単純に C プログラムのコンパイルに使用するとみなすことはできず、g++ は C++ プログラムのコンパイルに使用されます。興味のある読者は、より詳細な情報を参照してください。