C コードと C++ コードの混在使用
テクニカル・ノート 46551
アーキテクチャ:
All
コンポーネント:
compiler
更新日:
2018/01/23 8:36
はじめに
C++プロジェクトからC関数を呼び出したい、あるいはCプロジェクトからC++関数を呼出したい場合があります。
このテクニカルノートでは、CとC++を混在させる際に考慮すべき点をいくつか挙げています。 これは完全なガイドではなく、いくつかの一般的な障害と解決法を説明しているものです。
考慮すべき事項
1.
Cリンケージを使用してください。extern "C" { // ユーザ関数定義 } をヘッダファイルに置きます。
C++およびCヘッダーファイルの両方にこれが必要であることに注意してください:
- C関数がC ++関数を呼び出せるようにするため
- C++メソッドがC関数を呼び出せるようにするため
2.
C++には、より厳密な型チェックがあります。 たとえば、次のC関数の場合:
void LCD_DisplayString(const uint8_t *text);
Cでは、次のように呼び出すことができます。:
LCD_DisplayString("RTOS START");
C++では、コンパイルするために"RTOS START" を uint8_t* (char* から) にキャストする必要があります。 キャストより良い方法は、以下(3)を参照してください。
3.
CインタフェースをC ++クラスにラップします。たとえば、上記の "LCD_DisplayString"関数は、LCD::DisplayString()クラスにラップすることができます。
C++ のオーバーロードを使用すると、 char *とuint8_t *の間のキャストはLCDクラスメソッド内に隠すことができます:
void LCD::DisplayString(const char *text);
void LCD::DisplayString(const uint8_t *text);
言い換えれば、C++コード内でのキャストの必要がなくなります。
4.
一部の領域では、C++ は異なった挙動を示します。 例えば:
const int myglobal
C++のグローバル定数は静的なリンケージを持つため、C++ではグローバルではありません。
また、例えば、次のvolatileアクセスは、C++では必ずしも実行されません:
void access(void) {
*((volatile uint8_t*)0x20000000);
}
Cでは、このvolatileアクセスは実行されます。(オブジェクトがvoidコンテキストでアクセスされるとき、C言語仕様とC ++言語仕様が異なります) 問題を避けるため、純粋な Cコードは Cとしてコンパイルしてください (例えば、ファイル名の拡張子が".c"のRTOS あるいは BSP コード)。上記のコードに対してC++ジョンパイラは ワーニングを出力します: Warning[Pe174]: expression has no effect.
5.
C++のアプリケーションで Cコードを使用したい場合、Cコードを、別の (ライブラリ) プロジェクトにすることを検討してください。C(ライブラリ)プロジェクトは、C ++プロジェクトと同じワークスペースに配置して、高速にアクセスできます。C++プロジェクトのグループ内でCコードを使用する場合と比較して、いくつかの利点があります:
- コンパイルオプションを明確に区別することができる
- ビルド時間を速くできる (固定コードの再ビルドの必要がない)
6.
CライブラリがRTOSの場合は、RTOSヒープ使用、RTOS起動などの追加の課題があります。Technical Note 90383 を参照してください。RTOSベンダーが、これらの課題の解決のためにC++サンプル、ドキュメント、コードを提供していることもあります。繰り返しですが、RTOSのコードが Cで書かれている場合は、Cとしてコンパイルしてください。
追加情報
以下のスクリーンショットと Example project for IAR Embedded Workbench for ARMを参照してください。
全ての製品名は、それぞれの所有者の商標または登録商標です