CコードでのC ++ライブラリの使用


102

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

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

私は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でstruct Xとして宣言する必要があります。ここで、XはC ++オブジェクトです。

これらはすべて、C ++のウィザードである友人の好意によるものです。


5
やや遅いですが、C ++のCラッパーに関する小さなハウツーを書きました:teddy.ch/c
Teddy

回答:


69

はい、これは確かに可能です。以下を使用して関数を宣言するインターフェイス層をC ++で作成する必要がありますextern "C"

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

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

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


extern "C"宣言のみに配置する必要があります(定義には配置しないでください)?「関数を宣言するレイヤー」について言及しましたが、サンプルコードも定義です。つまり、ヘッダーファイルまたはソースファイル(またはその両方)に配置する必要がありますか?
kyriakosSt

@KyrSt:関数宣言を含むヘッダーファイルがある場合は、少なくともextern "C"そこに配置する必要があります。コンパイラーは、それを定義に追加する必要があるかどうかを通知します。
グレッグヒューギル2017年

23

C ++よくある質問Liteは:"CおよびC ++コードを混在させる方法"

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

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

12

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


2
longjump呼び出しについての素晴らしい点。私はそれらを直接使用しませんが、私が使用するテストフレームワークはそれらを実装しています。覚えておくべきこと。おかげで
ミシャM

3

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

extern "C"

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.