+
+
+Home
+| Search
+| D
+
+
+Last update Mon Jun 06 2005
+
+
+
+Interfacing to C
+
+ D is designed to fit comfortably with a C compiler for the target
+ system. D makes up for not having its own VM by relying on the
+ target environment's C runtime library. It would be senseless to
+ attempt to port to D or write D wrappers for the vast array of C APIs
+ available. How much easier it is to just call them directly.
+
+
+ This is done by matching the C compiler's data types, layouts,
+ and function call/return sequences.
+
+
Calling C Functions
+
+ C functions can be called directly from D. There is no need for
+ wrapper functions, argument swizzling, and the C functions do not
+ need to be put into a separate DLL.
+
+
+ The C function must be declared and given a calling convention,
+ most likely the "C" calling convention, for example:
+
+
+
+
+ extern (C) int strcmp(char* string1, char* string2);
+ |
+
+ and then it can be called within D code in the obvious way:
+
+
+
+
+ import std.string;
+ int myDfunction(char[] s)
+ {
+ return strcmp(std.string.toStringz(s), "foo");
+ }
+ |
+
+ There are several things going on here:
+
+
+ - D understands how C function names are "mangled" and the
+ correct C function call/return sequence.
+
+
- C functions cannot be overloaded with another C function
+ with the same name.
+
+
- There are no __cdecl, __far, __stdcall, __declspec, or other
+ such C type modifiers in D. These are handled by attributes, such
+ as extern (C).
+
+
- There are no const or volatile type modifiers in D. To declare
+ a C function that uses those type modifiers, just drop those
+ keywords from the declaration.
+
+
- Strings are not 0 terminated in D. See "Data Type Compatibility"
+ for more information about this. However, string literals in D are
+ 0 terminated.
+
+
+ C code can correspondingly call D functions, if the D functions
+ use an attribute that is compatible with the C compiler, most likely
+ the extern (C):
+
+
+
+
+ // myfunc() can be called from any C function
+ extern (C)
+ {
+ void myfunc(int a, int b)
+ {
+ ...
+ }
+ }
+ |
+
+
Storage Allocation
+
+ C code explicitly manages memory with calls to malloc() and
+ free(). D allocates memory using the D garbage collector,
+ so no explicit free's are necessary.
+
+
+ D can still explicitly allocate memory using c.stdlib.malloc()
+ and c.stdlib.free(), these are useful for connecting to C
+ functions that expect malloc'd buffers, etc.
+
+
+ If pointers to D garbage collector allocated memory are passed to
+ C functions, it's critical to ensure that that memory will not
+ be collected by the garbage collector before the C function is
+ done with it. This is accomplished by:
+
+
+
+ - Making a copy of the data using c.stdlib.malloc() and passing
+ the copy instead.
+
+
- Leaving a pointer to it on the stack (as a parameter or
+ automatic variable), as the garbage collector will scan the stack.
+
+
- Leaving a pointer to it in the static data segment, as the
+ garbage collector will scan the static data segment.
+
+
- Registering the pointer with the garbage collector with the
+ gc.addRoot() or gc.addRange() calls.
+
+
+
+ An interior pointer to the allocated memory block is sufficient
+ to let the GC
+ know the object is in use; i.e. it is not necessary to maintain
+ a pointer to the beginning of the allocated memory.
+
+
+ The garbage collector does not scan the stacks of threads not
+ created by the D Thread interface. Nor does it scan the data
+ segments of other DLL's, etc.
+
+
Data Type Compatibility
+
+
+
+
+ | D type |
+ C type |
+
+
+
+ | void |
+ void |
+
+
+
+ | bit |
+ no equivalent |
+
+
+
+ | byte |
+ signed char |
+
+
+
+ | ubyte |
+ unsigned char |
+
+
+
+ | char |
+ char (chars are unsigned in D) |
+
+
+
+ | wchar |
+ wchar_t (when sizeof(wchar_t) is 2) |
+
+
+
+ | dchar |
+ wchar_t (when sizeof(wchar_t) is 4) |
+
+
+
+ | short |
+ short |
+
+
+
+ | ushort |
+ unsigned short |
+
+
+
+ | int |
+ int |
+
+
+
+ | uint |
+ unsigned |
+
+
+
+ | long |
+ long long |
+
+
+
+ | ulong |
+ unsigned long long |
+
+
+
+ | float |
+ float |
+
+
+
+ | double |
+ double |
+
+
+
+ | real |
+ long double |
+
+
+
+ | ifloat |
+ float _Imaginary |
+
+
+
+ | idouble |
+ double _Imaginary |
+
+
+
+ | ireal |
+ long double _Imaginary |
+
+
+
+ | cfloat |
+ float _Complex |
+
+
+
+ | cdouble |
+ double _Complex |
+
+
+
+ | creal |
+ long double _Complex |
+
+
+
+ | struct |
+ struct |
+
+
+
+ | union |
+ union |
+
+
+
+ | enum |
+ enum |
+
+
+
+ | class |
+ no equivalent |
+
+
+
+ | type* |
+ type * |
+
+
+
+ | type[dim] |
+ type[dim] |
+
+
+
+ | type[dim]* |
+ type(*)[dim] |
+
+
+
+ | type[] |
+ no equivalent |
+
+
+
+ | type[type] |
+ no equivalent |
+
+
+
+ | type function(parameters) |
+ type(*)(parameters) |
+
+
+
+ | type delegate(parameters) |
+ no equivalent |
+
+
+
+
+
+
+ These equivalents hold for most 32 bit C compilers. The C standard
+ does not pin down the sizes of the types, so some care is needed.
+
+
Calling printf()
+
+ This mostly means checking that the printf format specifier
+ matches the corresponding D data type.
+ Although printf is designed to handle 0 terminated strings,
+ not D dynamic arrays of chars, it turns out that since D
+ dynamic arrays are a length followed by a pointer to the data,
+ the %.*s format works perfectly:
+
+
+
+
+ void foo(char[] string)
+ {
+ printf("my string is: %.*s\n", string);
+ }
+ |
+
+ The printf format string literal
+ in the example doesn't end with \0. This is because string literals,
+ when they are not part of an initializer to a larger data structure,
+ have a \0 character helpfully stored after the end of them.
+
+
+ An improved D function for formatted output is
+ std.stdio.writef().
+
+
Structs and Unions
+
+ D structs and unions are analogous to C's.
+
+
+ C code often adjusts the alignment and packing of struct members
+ with a command line switch or with various implementation specific
+ #pragma's. D supports explicit alignment attributes that correspond
+ to the C compiler's rules. Check what alignment the C code is using,
+ and explicitly set it for the D struct declaration.
+
+
+ D does not support bit fields. If needed, they can be emulated
+ with shift and mask operations.
+
+
Interfacing to C++
+
+ D does not provide an interface to C++. Since D, however,
+ interfaces directly to C, it can interface directly to
+ C++ code if it is declared as having C linkage.
+
+
+ D class objects are incompatible with C++ class objects.
+
+
Feedback and Comments
+
+ Add feedback and comments regarding this
+ page.
+
+
+Copyright © 1999-2005 by Digital Mars, All Rights Reserved
+
+
+
+
+
+
+
+
+
+
diff -uNr dmd-0.128/dmd/html/d/intro.html dmd-0.129/dmd/html/d/intro.html
--- dmd-0.128/dmd/html/d/intro.html 2005-06-18 13:39:00.000000000 +0200
+++ dmd-0.129/dmd/html/d/intro.html 2005-07-30 11:51:48.000000000 +0200
@@ -72,6 +72,8 @@