htod
While D is binary compatible with C code, it cannot compile C code nor C header files. In order for D to link with C code, the C declarations residing in C header files need to be converted to a D module. htod is a migration tool to aid in converting C header files.
htod is built from the front end of the Digital Mars C and C++ compiler. It works just like a C or C++ compiler except that its output is a D module rather than object code.
The macro __HTOD__ is predefined and set to 1, which is handy for improving C header files to give better D output.
Download
Usage
htod cheader.h [dimport.d] [-cpp] [-hc] [-hi] [-hs] [-ht] { C compiler switches }
where:
- cheader.h
- C or C++ header input file
- dimport.d
- D source code output file (defaults to cheader.d)
- -cpp
- Indicates a C++ header file
- -hc
- By default, htod will insert the C and C++ declarations in a file into the output file prefixed by //C . -hc will suppress this. Use only if you're confident that htod is generating the correct output file (such as if the header file was modified with __HTOD__).
- -hi
- By default, htod will represent a #include "file" with a corresponding import statement. The -hi will cause the declarations in the included file to be converted to D declarations as well. The declarations in all included files are parsed regardless. -hi is handy when replacing an entire hierarchy of include files with a single D import. System includes like #include <file> are not affected by -hi. See also -hs.
- -ht
- By default, htod will write types using typedef names as using those names. -ht will cause the underlying types to be used instead. This is very useful for "drilling down" layers of macros, typedefs, and #includes to find out the underlying type.
- -hs
- Works just like -hi, except that system includes are migrated as well.
- C compiler switches
- C or C++ compiler switches, such as -D and -I as documented for dmc.
Example
The C test.h file:
unsigned u; #define MYINT int void bar(int x, long y, long long z);
Translated with:
htod test.h
Produces the file 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 MYINT = int; void bar(int x, int y, long z);
The C declarations are prefixed by the string "//C ".
Type Mappings
C types are mapped as follows. These mappings are correct for Digital Mars C/C++, but may not be correct for your C compiler. D basic types have fixed sizes, while C basic type sizes are implementation defined.
C type | D type |
---|---|
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 |
Limitations
There is no one to one correspondence of C declarations to D declarations. A review of the D module output will be necessary to ensure the right decisions are made. Furthermore:
- Wherever practical, C headers should be written using typedef's and enum's rather than macros. htod will attempt to convert simple macro #define's to alias and const declarations. Even so, macros are fully expanded before further analysis.
- No attempt is made to convert C conditional compilation into D version or static if declarations.
- No output is generated for false conditional compilation sections.
- htod converts declarations only, it does not convert C code.
- Declarations with C++ linkage cannot be converted. A C interface must be made for any C++ code.
- C language extensions present in the C .h file may not be recognized.
- Pragmas are not translated.
- The tag names are assumed to not collide with names in the regular name space.
- Any character data that is not ASCII will need to be converted as necessary to UTF.
- The C char type is assumed to map to the D char type. However, these should be examined individually to see if they should instead be translated to byte or ubyte types. Whether the C char type is signed or unsigned is implementation defined. The D char type is unsigned.
- Named C enum members are not inserted into the surrounding scope as they are in C.
- D modules are each in their own name space, but C header files are all in the same global name space. This means that D references to names defined in other modules may need to be qualified.
Bugs
- Anything other than the default struct member alignment is not accounted for.
- No Linux version.