Improve this page Github へのログインが必要です。 簡単な修正は、ここから fork、オンライン編集、pull request ができます。 大きな修正については、 通常の clone で行って下さい。 Page wiki 関連するWikiページを参照・編集 English このページの英語版(原文)

htod

D は C のコードとのバイナリ互換性はありますが、 CのコードをコンパイルしたりCのヘッダを読み込むことはできません。 DとCのコードをリンクするためには、ヘッダにあるCの宣言を、 Dのモジュールへと変換する必要があります。 htod は、 Cのヘッダからの変換をサポートする手助けとなるツールです。

htod は Digital Mars C/C++ コンパイラのフロントエンドを元に作成されています。 出力がオブジェクトコードではなくDのモジュールであることを除けば、 あたかもC/C++コンパイラであるかのように動作します。

マクロ __HTOD__ があらかじめ 1 に定義されています。 このマクロを使うことで、D へ変換しやすい C のヘッダを書くのが簡単になります。

ダウンロード

htod

使い方

htod cheader.h [dimport.d] [-cpp] [-hc] [-hi] [-hs] [-ht] { C compiler switches }

それぞれのオプションの意味は以下の通りです。

cheader.h
C/C++ のヘッダファイル (入力)
dimport.d
D のソースコードファイル (出力) (デフォルトは cheader.d)
-cpp
ヘッダが C++ で書かれていることを示す
-hc
デフォルトでは、htod はC/C++での宣言をそのまま //C でコメントアウトした形でファイルに付け加えます。 -hc はこの動作を抑制します。 htod が正しい結果を出力していることに確信が持てるときだけ このオプションを使ってください。 (例えば __HTOD__を使ったヘッダを変換しているときなど)
-hi
デフォルトでは、htod#include "file" を 対応する import 文に置き換えます。 -hi を指定すると、 #include先の宣言も含めて全てをDの宣言に変換して出力するようになります。 #include先の内容の解析はこのオプション指定にかかわらず行われます。 -hi は、#include階層全体を ひとつのDのインポートモジュールに変換したいときに役に立ちます。 #include <file> のようなシステム#includeについては、 -hi は影響しません。 -hs も参照のこと。
-ht
デフォルトでは、htod はtypedefされた型名はそのまま使うようにして 変換します。 -ht を指定すると、対応する元の型に置き換えて出力が 行われます。これは、マクロやtypedef、#includeの層を掘り下げて 元々の型を探り当てるときに役立ちます。
-hs
-hi と似ていますが、こちらは更にシステム#includeについても 同様に変換出力を行います。
Cコンパイラ スイッチ
C/C++ コンパイラに対するスイッチ指定 (-D-I など)は dmc のドキュメントを参照してください。 )

C の test.h ファイルを:

unsigned u;
#define MYINT int
void bar(int x, long y, long long z);

次のコマンドで変換すると:

htod test.h

test.d というファイルが生成されます。

/* Converted to D from test.h by htod */
module test;
//C     unsigned u;
extern (C):
uint u;
//C     #define MYINT int
//C     void bar(int x, long y, long long z);
alias int MYINT;
void  bar(int x, int y, long z);

Cでの対応する宣言が "//C " コメントで残されています。

型の対応関係

C の型は以下の表の通り変換されます。これらの対応は Digital Mars C/C++ に関しては正確ですが、他のCコンパイラにとっては不適切かもしれません。 Dの基本型のサイズは規格で固定されていますが、 Cの型のサイズは処理系依存となっているのが原因です。

C から D への型対応関係
C の型 D の型
void void
_Bool bool
wchar_t wchar
char char
signed char byte
unsigned char ubyte
short short
unsigned short ushort
int int
unsigned uint
long int
unsigned long uint
long long long
unsigned long long ulong
float float
double double
long double real
_Imaginary float ifloat
_Imaginary double idouble
_Imaginary long double ireal
_Complex float cfloat
_Complex double cdouble
_Complex long double creal

制限事項

Cの宣言とDの宣言の間には、厳密な1対1対応は存在しません。 必ず、出力されたDモジュールの内容を見て、 正しく解釈されているか確認してから使うようにしてください。 他にもいくつか制限があります。

  1. 可能な限り、 C のヘッダはマクロではなく typedefenum を使って記述されているべきです。 htod は単純な #define マクロについては、aliasconst 宣言への変換を試みます。 とはいえ、ヘッダ内でのマクロ使用については解析前に全て展開されます。
  2. C の条件コンパイルを D の versionstatic if 宣言へと変換することは一切ありません。
  3. 条件コンパイル条件が偽となっている部分については、 なにも出力されません。
  4. htod は宣言のみを変換します。 Cのコードは変換しません。
  5. C++リンケージを持つ宣言は変換できません。 C++コードについては、まずCインターフェイスの作成が必要です。
  6. C のヘッダファイル中で使われた言語拡張については、 認識されない可能性があります。
  7. pragma は変換されません。
  8. タグ名は通常の名前空間と衝突しないことが 仮定されています。
  9. ASCII外の文字データは、 必要ならばUTFに変換しておく必要があります。
  10. C の char は D の char 型に対応すると仮定されています。しかしながら、 これについては個別にチェックして、byteubyte 型の方が適切ではないかチェックした方がよいでしょう。C の char 型がsignedかunsignedかは実装依存ですが、D の char 型はunsignedです。
  11. C の名前付き列挙体のメンバーは、Cでそうであるのと同様に、 周囲のスコープへと挿入されます。
  12. D のモジュールはそれぞれ個別の名前空間を持ちますが、 Cのヘッダファイルは全て共通のグローバル名前空間に置かれます。これは、 他のDのモジュールで宣言された名前への参照については、 修飾が必要となることを意味しています。

バグ

  1. デフォルトの構造体アラインメント以外は 考慮されていません。
  2. Linux版はありません。