web-dev-qa-db-ja.com

CコードでC ++ライブラリを使用する

データを管理するためのさまざまなクラスを提供するC++ライブラリがあります。ライブラリのソースコードがあります。

ライブラリをCコードとC++コードで同時に使用できるように、C++ APIを拡張してC関数呼び出しをサポートしたい。

GNUツールチェーン(gcc、glibcなど)を使用しているため、言語とアーキテクチャのサポートは問題になりません。

これが技術的に不可能な理由はありますか?

気をつけなければならないgotchaのはありますか?

これに関して利用可能なリソース、サンプルコード、ドキュメントはありますか?


私が見つけた他のいくつかのこと:

  1. 以下を使用して、Cコードで使用する必要があるC++ヘッダーをラップします。
#ifdef __cplusplus
extern "C" {  
#endif  
//  
// Code goes here ...  
//  
#ifdef __cplusplus  
} // extern "C"  
#endif
  1. Cに含まれていない別のヘッダーファイルに「実際の」C++インターフェイスを保持します。ここで PIMPLの原則を考えてください#ifndef __cplusplus #errorを使用すると、狂気を検出するのに役立ちます。
  2. Cコードの名前としてのC++識別子の注意
  3. CコンパイラとC++コンパイラ間でサイズが異なる列挙型。 GNUツールチェーンを使用している場合はおそらく問題ではありませんが、それでも注意してください。
  4. Cが混乱しないように、構造体については次の形式に従ってください。

    typedef struct X { ... } X
    
  5. 次に、C++オブジェクトを渡すためにポインターを使用します。それらは、Cでstruct Xとして宣言する必要があります(XはC++オブジェクトです)。

これはすべて、C++の魔法使いである友人のご厚意によるものです。

96
Misha M

はい、これは確かに可能です。 _extern "C"_で関数を宣言するインターフェース層をC++で記述する必要があります。

_extern "C" int foo(char *bar)
{
    return realFoo(std::string(bar));
}
_

次に、Cモジュールからfoo()を呼び出します。Cモジュールは、C++で実装されているrealFoo()関数に呼び出しを渡します。

データメンバーとメソッドを含む完全なC++クラスを公開する必要がある場合は、この単純な関数の例よりも多くの作業が必要になる場合があります。

66
Greg Hewgill

C++ FAQ Lite: "CコードとC++コードを混在させる方法"

これらの質問への回答には、いくつかの落とし穴が記載されています。

  • [32.8] C関数との間でC++クラスのオブジェクトをやり取りするにはどうすればよいですか?
  • [32.9] C関数はC++クラスのオブジェクト内のデータに直接アクセスできますか?
22
Alex B

主な落とし穴:Cでは例外をキャッチできません。C++コードで例外が発生する可能性がある場合は、CコードまたはC++ラッパーを非常に慎重に記述してください。逆に、スタック上のC++オブジェクトのデストラクタを呼び出すために、Cコードのメカニズム(つまり、ロングジャンプ)のような例外(さまざまなスクリプト言語で見られる)は必要ありません。

11
ejgottl

c/C++コードを混在させることができます。 main()関数がC++の場合、c関数が宣言されていることを確認するだけです。

extern "C"

メインがCである場合、静的変数を除き、おそらく大丈夫です。静的変数を持つコンストラクタは、main()の開始前に呼び出されることになっています。 Cがメインの場合、これは起こりません。静的変数がたくさんある場合、最善の方法は静的変数をシングルトンに置き換えることです。

3
David Nehme