Difference between revisions of "D binding for C"

From D Wiki
Jump to: navigation, search
Line 91: Line 91:
 
"string"w // for 16 bit wide characters
 
"string"w // for 16 bit wide characters
 
"string"d // for 32 bit wide characters
 
"string"d // for 32 bit wide characters
 +
</syntaxhighlight>
 +
 +
== Macros ==
 +
Lists of macros like:
 +
 +
 +
<syntaxhighlight lang="C">
 +
#define FOO 1
 +
#define BAR 2
 +
#define ABC 3
 +
#define DEF 40
 +
</syntaxhighlight>
 +
 +
can be replaced with:
 +
 +
<syntaxhighlight lang="D">
 +
enum
 +
{  FOO = 1,
 +
    BAR = 2,
 +
    ABC = 3,
 +
    DEF = 40
 +
}
 +
</syntaxhighlight>
 +
 +
or with:
 +
 +
<syntaxhighlight lang="D">
 +
const int FOO = 1;
 +
const int BAR = 2;
 +
const int ABC = 3;
 +
const int DEF = 40;
 +
</syntaxhighlight>
 +
 +
Function style macros, such as:
 +
 +
<syntaxhighlight lang="C">
 +
#define MAX(a,b) ((a) < (b) ? (b) : (a))
 +
</syntaxhighlight>
 +
 +
can be replaced with functions:
 +
 +
<syntaxhighlight lang="D">
 +
int MAX(int a, int b) { return (a < b) ? b : a; }
 +
</syntaxhighlight>
 +
 +
The functions, however, won't work if they appear inside static initializers that must be evaluated at compile time rather than runtime. To do it at compile time, a template can be used:
 +
 +
<syntaxhighlight lang="C">
 +
#define GT_DEPTH_SHIFT  (0)
 +
#define GT_SIZE_SHIFT  (8)
 +
#define GT_SCHEME_SHIFT (24)
 +
#define GT_DEPTH_MASK  (0xffU << GT_DEPTH_SHIFT)
 +
#define GT_TEXT        ((0x01) << GT_SCHEME_SHIFT)
 +
 +
/* Macro that constructs a graphtype */
 +
#define GT_CONSTRUCT(depth,scheme,size) \
 +
((depth) | (scheme) | ((size) << GT_SIZE_SHIFT))
 +
 +
/* Common graphtypes */
 +
#define GT_TEXT16  GT_CONSTRUCT(4, GT_TEXT, 16)
 +
</syntaxhighlight>
 +
 +
The corresponding D version would be:
 +
 +
<syntaxhighlight lang="D">
 +
const uint GT_DEPTH_SHIFT  = 0;
 +
const uint GT_SIZE_SHIFT  = 8;
 +
const uint GT_SCHEME_SHIFT = 24;
 +
const uint GT_DEPTH_MASK  = 0xffU << GT_DEPTH_SHIFT;
 +
const uint GT_TEXT        = 0x01 << GT_SCHEME_SHIFT;
 +
 +
// Template that constructs a graphtype
 +
template GT_CONSTRUCT(uint depth, uint scheme, uint size)
 +
{
 +
// notice the name of the const is the same as that of the template
 +
const uint GT_CONSTRUCT = (depth | scheme | (size << GT_SIZE_SHIFT));
 +
}
 +
 +
// Common graphtypes
 +
const uint GT_TEXT16 = GT_CONSTRUCT!(4, GT_TEXT, 16);
 
</syntaxhighlight>
 
</syntaxhighlight>

Revision as of 04:11, 24 February 2014

While D cannot directly compile C source code, it can easily interface to C code, be linked with C object files, and call C functions in DLLs. The interface to C code is normally found in C .h files. So, the trick to connecting with C code is in converting C .h files to D modules. This turns out to be difficult to do mechanically since inevitably some human judgement must be applied. This is a guide to doing such conversions.

Preprocessor

.h files can sometimes be a bewildering morass of layers of macros, #include files, #ifdef's, etc. D doesn't include a text preprocessor like the C preprocessor, so the first step is to remove the need for it by taking the preprocessed output. For DMC (the Digital Mars C/C++ compiler), the command:

dmc -c program.h -e -l

will create a file program.lst which is the source file after all text preprocessing.

Remove all the #if, #ifdef, #include, etc. statements.

Linkage

Generally, surround the entire module with:

extern (C)
{
     /* ...file contents... */
}

to give it C linkage.

Types

A little global search and replace will take care of renaming the C types to D types. The following table shows a typical mapping for 32 bit C code:

Mapping C type to D type
C type D type
long double real
unsigned long long ulong
long long long
unsigned long uint
long int
unsigned uint
unsigned short ushort
signed char byte
unsigned char ubyte
wchar_t wchar or dchar
bool bool, byte, int
size_t size_t
ptrdiff_t ptrdiff_t

NULL

NULL and ((void*)0) should be replaced with null. Numeric Literals Any ‘L’ or ‘l’ numeric literal suffixes should be removed, as a C long is (usually) the same size as a D int. Similarly, ‘LL’ suffixes should be replaced with a single ‘L’. Any ‘u’ suffix will work the same in D.

String Literals

In most cases, any ‘L’ prefix to a string can just be dropped, as D will implicitly convert strings to wide characters if necessary. However, one can also replace:

L"string"

with:

"string"w	// for 16 bit wide characters
"string"d	// for 32 bit wide characters

Macros

Lists of macros like:


#define FOO	1
#define BAR	2
#define ABC	3
#define DEF	40

can be replaced with:

enum
{   FOO = 1,
    BAR = 2,
    ABC = 3,
    DEF = 40
}

or with:

const int FOO = 1;
const int BAR = 2;
const int ABC = 3;
const int DEF = 40;

Function style macros, such as:

#define MAX(a,b) ((a) < (b) ? (b) : (a))

can be replaced with functions:

int MAX(int a, int b) { return (a < b) ? b : a; }

The functions, however, won't work if they appear inside static initializers that must be evaluated at compile time rather than runtime. To do it at compile time, a template can be used:

#define GT_DEPTH_SHIFT  (0)
#define GT_SIZE_SHIFT   (8)
#define GT_SCHEME_SHIFT (24)
#define GT_DEPTH_MASK   (0xffU << GT_DEPTH_SHIFT)
#define GT_TEXT         ((0x01) << GT_SCHEME_SHIFT)

/* Macro that constructs a graphtype */
#define GT_CONSTRUCT(depth,scheme,size) \
	((depth) | (scheme) | ((size) << GT_SIZE_SHIFT))

/* Common graphtypes */
#define GT_TEXT16  GT_CONSTRUCT(4, GT_TEXT, 16)

The corresponding D version would be:

const uint GT_DEPTH_SHIFT  = 0;
const uint GT_SIZE_SHIFT   = 8;
const uint GT_SCHEME_SHIFT = 24;
const uint GT_DEPTH_MASK   = 0xffU << GT_DEPTH_SHIFT;
const uint GT_TEXT         = 0x01 << GT_SCHEME_SHIFT;

// Template that constructs a graphtype
template GT_CONSTRUCT(uint depth, uint scheme, uint size)
{
 // notice the name of the const is the same as that of the template
 const uint GT_CONSTRUCT = (depth | scheme | (size << GT_SIZE_SHIFT));
}

// Common graphtypes
const uint GT_TEXT16 = GT_CONSTRUCT!(4, GT_TEXT, 16);