114

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

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

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

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

注意する必要がある落とし穴はありますか?

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


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

  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 では、X が C++ オブジェクトである struct X として宣言するだけです。

これはすべて、C++ の達人である友人の厚意によるものです。

4

4 に答える 4

77

はい、これは確かに可能です。次のように関数を宣言するインターフェイス レイヤーを C++ で記述する必要がありますextern "C"

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

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

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

于 2008-10-13T23:33:49.063 に答える
23

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

これらの質問への回答で、いくつかの落とし穴が説明されています。

  • [32.8] C 関数との間で C++ クラスのオブジェクトを渡すにはどうすればよいですか?
  • [32.9] 私の C 関数は、C++ クラスのオブジェクトのデータに直接アクセスできますか?
于 2008-10-13T23:46:19.710 に答える
13

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

于 2008-10-13T23:45:31.630 に答える
3

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

extern "C"

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

于 2008-10-13T23:40:34.060 に答える