$(DDOC $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE ) $(SPEC_S ImportC, $(DDOC_BLANKLINE ) $(HEADERNAV_TOC $(HEADERNAV_ITEM examples, Quick Examples) $(HEADERNAV_ITEM dialect, ImportC Dialect) $(HEADERNAV_SUBITEMS command-line, Invoking ImportC, $(HEADERNAV_ITEM command-line, ImportC Files on the Command Line) $(HEADERNAV_ITEM importing, Importing C Files from D Code) ) $(HEADERNAV_SUBITEMS preprocessor, Preprocessor, $(HEADERNAV_ITEM auto-cpp, Running the Preprocessor Automatically) $(HEADERNAV_ITEM manual-cpp, Running the Preprocessor Manually) $(HEADERNAV_ITEM defines, Preprocessor Macros) ) $(HEADERNAV_ITEM predefined-macros, Predefined Macros) $(HEADERNAV_SUBITEMS preprocessor-directives, Preprocessor Directives, $(HEADERNAV_ITEM line-control, Line control) $(HEADERNAV_ITEM linemarker, Linemarker) $(HEADERNAV_ITEM pragma, pragma) ) $(HEADERNAV_SUBITEMS implementation, Implementation, $(HEADERNAV_ITEM enums, Enums) $(HEADERNAV_ITEM bitfields, Bit Fields) $(HEADERNAV_ITEM implicit-function-declaration, Implicit Function Declarations) $(HEADERNAV_ITEM pragma-STDC-FENV_ACCESS, #pragma STDC FENV_ACCESS) ) $(HEADERNAV_SUBITEMS limitations, Limitations, $(HEADERNAV_ITEM exceptions, Exception Handling) $(HEADERNAV_ITEM const, Const) $(HEADERNAV_ITEM volatile, Volatile) $(HEADERNAV_ITEM restrict, Restrict) $(HEADERNAV_ITEM _atomic, _Atomic) $(HEADERNAV_ITEM compatible_types, Compatible Types) $(HEADERNAV_ITEM same_only_different, Same only Different Types) $(HEADERNAV_ITEM _generic, _Generic) ) $(HEADERNAV_SUBITEMS extensions, Extensions, $(HEADERNAV_ITEM asmstatements, Asm statement) $(HEADERNAV_ITEM forward-references, Forward References) $(HEADERNAV_ITEM cpp-tag-symbols, C++ Style Tag Symbols) $(HEADERNAV_ITEM ctfe, Compile Time Function Execution) $(HEADERNAV_ITEM inlining, Function Inlining) $(HEADERNAV_ITEM enumbasetype, Enum Base Types) $(HEADERNAV_ITEM register, Register Storage Class) $(HEADERNAV_ITEM typeof, typeof Operator) $(HEADERNAV_ITEM __import, Import Declarations) $(HEADERNAV_ITEM controlZ, Control Z is End Of File) ) $(HEADERNAV_SUBITEMS gnu-clang-extensions, Gnu and Clang Extensions, $(HEADERNAV_ITEM __attribute__, __attribute__ Extensions) $(HEADERNAV_ITEM noreturn, __attribute__((noreturn))) ) $(HEADERNAV_SUBITEMS visualc-extensions, Visual C Extensions, $(HEADERNAV_ITEM __stdcall, __stdcall Function Calling Convention) $(HEADERNAV_ITEM __declspec, __declspec Attribute Extensions) $(HEADERNAV_ITEM __pragma, __pragma Attribute Extensions) ) $(HEADERNAV_SUBITEMS digital-mars-extensions, Digital Mars C Extensions, $(HEADERNAV_ITEM __stdcall, __stdcall Function Calling Convention) $(HEADERNAV_ITEM __declspec, __declspec Attribute Extensions) ) $(HEADERNAV_SUBITEMS d-side, ImportC from D's Point of View, $(HEADERNAV_ITEM module-name, Module Name) $(HEADERNAV_ITEM extern-C, extern (C)) $(HEADERNAV_ITEM enums, Enums) $(HEADERNAV_ITEM tag-symbols, Tag Symbols) ) $(HEADERNAV_ITEM wrapping, Wrapping C Code) $(HEADERNAV_ITEM warnings, Warnings) $(HEADERNAV_ITEM builtins, $(TT __builtins.di)) $(HEADERNAV_ITEM importcpp, ImportC++) $(HEADERNAV_SUBITEMS other-solutions, Other Solutions, $(HEADERNAV_ITEM dpp, dpp by Atila Neves) $(HEADERNAV_ITEM dstep, DStep by Jacob Carlborg) $(HEADERNAV_ITEM htod, htod by Walter Bright) ) $(HEADERNAV_ITEM internals, How ImportC Works) ) $(DDOC_BLANKLINE ) $(P ImportC is a C compiler embedded into the D implementation. It enables direct importation of C files, without needing to manually prepare a D file corresponding to the declarations in the C file. It directly compiles C files into modules that can be linked in with D code to form an executable. It can be used as a C compiler to compile and link 100% C programs. ) $(DDOC_BLANKLINE ) $(NOTE ImportC and $(LINK2 https://dlang.org/spec/betterc.html, BetterC) are very different. ImportC is an actual C compiler. BetterC is a subset of D that relies only on the existence of the C Standard library. BetterC code can be linked with ImportC code, too.) $(DDOC_BLANKLINE )

$(LNAME2 examples, Quick Examples)

$(DDOC_BLANKLINE ) $(P C code in file $(TT hello.c):) $(DDOC_BLANKLINE ) $(CCODE #include <stdio.h> int main() { printf("hello world\n"); return 0; } ) $(DDOC_BLANKLINE ) $(P Compile and run:) $(DDOC_BLANKLINE ) $(CONSOLE dmd hello.c ./hello hello world ) $(DDOC_BLANKLINE ) $(P C function in file $(TT functions.c):) $(DDOC_BLANKLINE ) $(CCODE int square(int i) { return i * i; } ) $(DDOC_BLANKLINE ) $(P D program in file $(TT demo.d):) $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD import) std.stdio; $(D_KEYWORD import) functions; $(D_KEYWORD void) main() { $(D_KEYWORD int) i = 7; writefln($(D_STRING "The square of %s is %s"), i, square(i)); } ) $(DDOC_BLANKLINE ) $(P Compile and run:) $(DDOC_BLANKLINE ) $(CONSOLE dmd demo.d functions.c ./demo The square of 7 is 49 ) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 dialect, ImportC Dialect)

$(DDOC_BLANKLINE ) $(P There are many versions of C. ImportC is an implementation of $(LINK2 https://en.wikipedia.org/wiki/C11_(C_standard_revision), ISO/IEC 9899:2011), which will be referred to as $(B C11). References to the C11 Standard will be C11 followed by the paragraph number. Prior versions, such as C99, C89, and K+R C, are not supported. ) $(DDOC_BLANKLINE ) $(IMPLEMENTATION_DEFINED Adjustment to the ImportC dialect is made to match the behavior of the C compiler that the D compiler is matched to, i.e. the $(ACC ). ) $(DDOC_BLANKLINE ) $(P Further adjustment is made to take advantage of some of the D implementation's capabilities.) $(DDOC_BLANKLINE ) $(NOTE This is not a C reference manual nor programming tutorial. It describes the specifics of the dialect of C that ImportC is, and how to use it effectively.) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 command-line, Invoking ImportC)

$(DDOC_BLANKLINE ) $(P The ImportC compiler can be invoked:) $(DDOC_BLANKLINE ) $(UL $(LI directly via the command line) $(LI indirectly via importing a C file) ) $(DDOC_BLANKLINE )

$(LNAME2 command-line, ImportC Files on the Command Line)

$(DDOC_BLANKLINE ) $(P ImportC files have one of the extensions .i, or .c. If no extension is given, .i is tried first, then .c. ) $(DDOC_BLANKLINE ) $(CONSOLE dmd hello.c ) $(DDOC_BLANKLINE ) $(P will compile hello.c with ImportC and link it to create the executable file hello (hello.exe on Windows) ) $(DDOC_BLANKLINE ) $(BEST_PRACTICE explicitly use a .i or .c extension when specifying C files on the command line.) $(DDOC_BLANKLINE )

$(LNAME2 importing, Importing C Files from D Code)

$(DDOC_BLANKLINE ) $(P Use the D $(GLINK2 module, ImportDeclaration):) $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD import) hello; ) $(DDOC_BLANKLINE ) $(P which will, if hello is not a D file, and has an extension .i or .c, compile hello with ImportC. ) $(DDOC_BLANKLINE )

$(LNAME2 preprocessor, Preprocessor)

$(DDOC_BLANKLINE ) $(P ImportC does not have a preprocessor. It is designed to compile C files after they have been first run through the C preprocessor. ImportC can automatically run the C preprocessor associated with the $(ACC ), or a preprocessor can be run manually. ) $(DDOC_BLANKLINE )

$(LNAME2 auto-cpp, Running the Preprocessor Automatically)

$(DDOC_BLANKLINE ) $(P If the C file has a $(TT .c) extension, ImportC will run the preprocessor for it automatically.) $(DDOC_BLANKLINE ) $(OL $(LI When compiling for Windows with the $(DDSUBLINK dmd, switch-m32omf, $(TT -m32omf)) switch, $(TT sppn.exe) will be used as the preprocessor.) $(LI When compiling for Windows with the $(DDSUBLINK dmd, switch-m32mscoff, $(TT -m32mscoff)) or the $(DDSUBLINK dmd, switch-m64, $(TT -m64)) switch, $(TT cl.exe /P /Zc:preprocessor) will be used as the preprocessor.) $(LI When compiling for OSX, the $(TT clang -E) preprocessor will be used.) $(LI Otherwise the $(TT cpp) preprocessor will be used.) ) $(DDOC_BLANKLINE ) $(P The druntime file $(TT src/importc.h) will automatically be $(TT #include)d.) $(DDOC_BLANKLINE ) $(P The $(DDSUBLINK dmd, switch-v, $(TT -v)) switch can be used to observe the command that invokes the preprocessor. ) $(DDOC_BLANKLINE ) $(P The $(DDSUBLINK dmd, switch-P, $(TT -P$(I preprocessorflag))) switch passes $(TT $(I preprocessorflag)) to the preprocessor. ) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 manual-cpp, Running the Preprocessor Manually)

$(DDOC_BLANKLINE ) $(P If the C file has a $(TT .i) extension, the file is presumed to be already preprocessed. Preprocessing can be run manually: ) $(DDOC_BLANKLINE )

$(LNAME2 spp,Digital Mars C Preprocessor sppn.exe)

$(DDOC_BLANKLINE ) $(P $(LINK2 https://www.digitalmars.com/ctg/sc.html, $(TT sppn.exe)) runs on Win32 and is invoked as:) $(DDOC_BLANKLINE ) $(CONSOLE sppn file.c ) $(DDOC_BLANKLINE ) $(P and the preprocessed output is written to $(TT file.i).) $(DDOC_BLANKLINE )

$(LNAME2 gcc-preprocessor, Gnu C Preprocessor)

$(DDOC_BLANKLINE ) $(P The $(LINK2 https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html, Gnu C Preprocessor) can be invoked as:) $(DDOC_BLANKLINE ) $(CONSOLE gcc -E file.c > file.i ) $(DDOC_BLANKLINE )

$(LNAME2 clang-preprocessor, Clang C Preprocessor)

$(DDOC_BLANKLINE ) $(P The Clang Preprocessor can be invoked as:) $(DDOC_BLANKLINE ) $(CONSOLE clang -E file.c -o file.i ) $(DDOC_BLANKLINE )

$(LNAME2 vc-preprocessor, Microsoft VC Preprocessor)

$(DDOC_BLANKLINE ) $(P The $(LINK2 https://docs.microsoft.com/en-us/cpp/preprocessor/c-cpp-preprocessor-reference?view=msvc-170, VC Preprocessor) can be invoked as:) $(DDOC_BLANKLINE ) $(CONSOLE cl /P /Zc:preprocessor file.c -Fifile.i ) $(DDOC_BLANKLINE ) $(P and the preprocessed output is written to $(TT file.i).) $(DDOC_BLANKLINE )

$(LNAME2 dmpp, dmpp C Preprocessor)

$(DDOC_BLANKLINE ) $(P The $(LINK2 https://github.com/DigitalMars/dmpp, dmpp C Preprocessor) can be invoked as:) $(DDOC_BLANKLINE ) $(CONSOLE dmpp file.c ) $(DDOC_BLANKLINE ) $(P and the preprocessed output is written to $(TT file.i).) $(DDOC_BLANKLINE )

$(LNAME2 defines, Preprocessor Macros)

$(DDOC_BLANKLINE ) $(P ImportC collects all the $(TT #define) macros from the preprocessor run when it is run automatically. The macros that look like manifest constants, such as:) $(DDOC_BLANKLINE ) $(CCODE #define COLOR 0x123456 ) $(DDOC_BLANKLINE ) $(P are interpreted as D manifest constant declarations of the form:) $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD enum) COLOR = 0x123456; ) $(DDOC_BLANKLINE ) $(P The variety of macros that can be interpreted as D declarations may be expanded, but will never encompass all the metaprogramming uses of C macros. ) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 predefined-macros, Predefined Macros)

$(DDOC_BLANKLINE ) $(P ImportC does not predefine any macros.) $(DDOC_BLANKLINE ) $(P To distinguish an ImportC compile vs some other C compiler, use:) $(DDOC_BLANKLINE ) $(CCODE #if __IMPORTC__ ) $(DDOC_BLANKLINE ) $(P $(TT __IMPORTC__) is defined in $(LINK2 https://github.com/dlang/dmd/blob/master/druntime/src/importc.h, $(TT src/importc.h)) which is automatically included when the preprocessor is run. $(TT importc.h) contains many macro definitions that are used to adapt various C source code vagaries to ImportC.) $(DDOC_BLANKLINE )

$(LNAME2 preprocessor-directives, Preprocessor Directives)

$(DDOC_BLANKLINE ) $(P ImportC supports these preprocessor directives:) $(DDOC_BLANKLINE )

$(LNAME2 line-control, Line control)

$(DDOC_BLANKLINE ) $(P C11 6.10.4) $(DDOC_BLANKLINE )

$(LNAME2 linemarker, Linemarker)

$(DDOC_BLANKLINE ) $(P $(LINK2 https://gcc.gnu.org/onlinedocs/gcc-11.1.0/cpp/Preprocessor-Output.html, linemarker) directives are normally embedded in the output of C preprocessors.) $(DDOC_BLANKLINE )

$(LNAME2 pragma, pragma)

$(DDOC_BLANKLINE ) $(P The following pragmas are supported:) $(DDOC_BLANKLINE ) $(UL $(LI $(TT #pragma pack ( ))) $(LI $(TT #pragma pack ( show ))) $(LI $(TT #pragma pack ( push ))) $(LI $(TT #pragma pack ( push , identifier ))) $(LI $(TT #pragma pack ( push , integer ))) $(LI $(TT #pragma pack ( push , identifier , integer ))) $(LI $(TT #pragma pack ( pop ))) $(LI $(TT #pragma pack ( pop PopList ))) ) $(DDOC_BLANKLINE )

$(LNAME2 implementation, Implementation)

$(DDOC_BLANKLINE ) $(P The implementation defined characteristics of ImportC are:) $(DDOC_BLANKLINE )

$(LNAME2 enums, Enums)

$(DDOC_BLANKLINE ) $(P $(I enumeration-constants) are always typed as int.) $(DDOC_BLANKLINE ) $(P The expression that defines the value of an $(I enumeration-constant) must be an integral type and evaluate to an integer value that fits in an int.) $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD enum) E { -10, 0x81231234 }; $(D_COMMENT // ok )$(D_KEYWORD enum) F { 0x812312345678 }; $(D_COMMENT // error, doesn't fit in int )$(D_KEYWORD enum) G { 1.0 }; $(D_COMMENT // error, not integral type )) $(DDOC_BLANKLINE ) $(P The enumerated type is int.) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 bitfields, Bit Fields)

$(DDOC_BLANKLINE ) $(P There are many implementation defined aspects of C11 bit fields. ImportC's behavior adjusts to match the behavior of the $(I associated C compiler) on the target platform. ) $(DDOC_BLANKLINE )

$(LNAME2 implicit-function-declaration, Implicit Function Declarations)

$(DDOC_BLANKLINE ) $(P Implicit function declarations:) $(DDOC_BLANKLINE ) $(CCODE int main() { func(); // implicit declaration of func() } ) $(DDOC_BLANKLINE ) $(P were allowed in K+R C and C89, but were invalidated in C99 and C11. Although many C compilers still support them, ImportC does not. ) $(DDOC_BLANKLINE ) $(RATIONALE Implicit function declarations are very error-prone and cause hard to find bugs.) $(DDOC_BLANKLINE )

$(LNAME2 pragma-STDC-FENV_ACCESS, #pragma STDC FENV_ACCESS)

$(DDOC_BLANKLINE ) $(P This is described in C11 7.6.1) $(DDOC_BLANKLINE ) $(GRAMMAR_INFORMATIVE #pragma STDC FENV_ACCESS on-off-switch $(DDOC_BLANKLINE ) on-off-switch: ON OFF DEFAULT ) $(DDOC_BLANKLINE ) $(P It is completely ignored.) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 limitations, Limitations)

$(DDOC_BLANKLINE )

$(LNAME2 exceptions, Exception Handling)

$(DDOC_BLANKLINE ) $(P ImportC is assumed to never throw exceptions. setjmp and longjmp are not supported.) $(DDOC_BLANKLINE )

$(LNAME2 const, Const)

$(DDOC_BLANKLINE ) $(P C11 specifies that const only applies locally. const in ImportC applies transitively, meaning that although $(CCODE int *const p;) means in C11 that p is a const pointer to int, in ImportC it means p is a const pointer to a const int.) $(DDOC_BLANKLINE )

$(LNAME2 volatile, Volatile)

$(DDOC_BLANKLINE ) $(P The volatile type-qualifier (C11 6.7.3) is ignored. Use of volatile to implement shared memory access is unlikely to work anyway, $(LINK2 #_atomic, _Atomic) is for that. To use volatile as a device register, call a function to do it that is compiled separately, or use inline assembler. ) $(DDOC_BLANKLINE )

$(LNAME2 restrict, Restrict)

$(DDOC_BLANKLINE ) $(P The restrict type-qualifier (C11 6.7.3) is ignored.) $(DDOC_BLANKLINE )

$(LNAME2 _atomic, _Atomic)

$(DDOC_BLANKLINE ) $(P The _Atomic type-qualifier (C11 6.7.3) is ignored. To do atomic operations, use an externally compiled function for that, or the inline assembler.) $(DDOC_BLANKLINE )

$(LNAME2 compatible_types, Compatible Types)

$(DDOC_BLANKLINE ) $(P $(I Compatible Types) (C11 6.7.2) are identical types in ImportC.) $(DDOC_BLANKLINE )

$(LNAME2 same_only_different, Same only Different Types)

$(DDOC_BLANKLINE ) $(P On some platforms, C long and unsigned long are the same size as int and unsigned int, respectively. On other platforms, C long and unsigned long are the same size as long long and unsigned long long. long double and long double _Complex can be same size as double and double _Complex. In ImportC, these types that are the same size and signed-ness are treated as the same types. ) $(DDOC_BLANKLINE )

$(LNAME2 _generic, _Generic)

$(DDOC_BLANKLINE ) $(P $(B Generic selection) expressions (C11 6.5.1.1) differ from ImportC. The types in $(LINK2 #same_only_different, Same only Different Types) are indistinguishable in the $(I type-name) parts of $(I generic-association). Instead of giving an error for duplicate types per C11 6.5.1.1-2, ImportC will select the first compatible $(I type-name) in the $(I generic-assoc-list). ) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 extensions, Extensions)

$(DDOC_BLANKLINE )

$(LNAME2 asmstatements, Asm statement)

$(DDOC_BLANKLINE ) $(P For the D language, asm is a standard keyword, and its construct is shared with ImportC. For the C language, asm is an extension (J.5.10), and the recommendation is to instead use __asm__. All alternative keywords for asm are translated by the druntime file $(TT src/importc.h) during the preprocessing stage.) $(DDOC_BLANKLINE ) $(P The asm keyword may be used to embed assembler instructions, its syntax is implementation defined. The Digital Mars D compiler only supports the dialect of inline assembly as described in the documentation of the $(LINK2 https://dlang.org/spec/iasm.html, D x86 Inline Assembler).) $(DDOC_BLANKLINE ) $(P asm in a function or variable declaration may be used to specify the mangle name for a symbol. Its use is analogous to $(LINK2 https://dlang.org/spec/pragma.html#mangle, pragma mangle).) $(DDOC_BLANKLINE ) $(CCODE char **myenviron asm("environ") = 0; $(DDOC_BLANKLINE ) int myprintf(char *, ...) asm("printf"); ) $(DDOC_BLANKLINE ) $(P Using asm to associate registers with variables is ignored.) $(DDOC_BLANKLINE )

$(LNAME2 forward-references, Forward References)

$(DDOC_BLANKLINE ) $(P Any declarations in scope can be accessed, not just declarations that lexically precede a reference.) $(DDOC_BLANKLINE ) $(CCODE Ta *p; // Ta is forward referenced struct Sa { int x; }; typedef struct Sa Ta; // Ta is defined ) $(DDOC_BLANKLINE ) $(CCODE struct S s; int* p = &s.t.x; // struct S definition is forward referenced struct S { int a; struct T t; }; // T still forward referenced struct T { int b; int x; }; // definition of struct T ) $(DDOC_BLANKLINE )

$(LNAME2 cpp-tag-symbols, C++ Style Tag Symbols)

$(DDOC_BLANKLINE ) $(P In C++, struct, union or enum tag symbols can be accessed without needing to be prefixed with the struct, union or enum keywords, as long as there is no other declaration with the same name at the same scope. ImportC behaves the same way.) $(DDOC_BLANKLINE ) $(P For example, the following code is accepted by both C++ and ImportC:) $(DDOC_BLANKLINE ) $(CCODE struct s { int a; }; $(DDOC_BLANKLINE ) void g(int s) { struct s* p = (struct s*)malloc(sizeof(struct s)); p->a = s; } ) $(DDOC_BLANKLINE ) $(P Whereas this is rejected by both C++ and ImportC, for the same reason.) $(DDOC_BLANKLINE ) $(CCODE struct s { int a; }; $(DDOC_BLANKLINE ) void g(int s) { s* p = (s*)malloc(sizeof(s)); p->a = s; } ) $(DDOC_BLANKLINE )

$(LNAME2 ctfe, Compile Time Function Execution)

$(DDOC_BLANKLINE ) $(P Evaluating constant expressions includes executing functions in the same manner as D's CTFE can. A $(I constant-expression) invokes CTFE.) $(DDOC_BLANKLINE ) $(P Examples:) $(DDOC_BLANKLINE ) $(CCODE _Static_assert("\x1"[0] == 1, "failed"); $(DDOC_BLANKLINE ) int mint1() { return -1; } _Static_assert(mint1() == -1, "failed"); $(DDOC_BLANKLINE ) const int a = 7; int b = a; // sets b to 7 ) $(DDOC_BLANKLINE )

$(LNAME2 inlining, Function Inlining)

$(DDOC_BLANKLINE ) $(P Functions for which the function body is present can be inlined by ImportC as well as by the D code that calls them.) $(DDOC_BLANKLINE )

$(LNAME2 enumbasetype, Enum Base Types)

$(DDOC_BLANKLINE ) $(P Enums are extended with an optional $(I EnumBaseType):) $(DDOC_BLANKLINE ) $(GRAMMAR $(GNAME EnumDeclaration): $(D enum) $(GLINK Identifier) $(D :) $(GLINK EnumBaseType) $(GLINK EnumBody) $(DDOC_BLANKLINE ) $(GNAME EnumBaseType): $(GLINK Type) ) $(DDOC_BLANKLINE ) $(P which, when supplied, causes the enum members to be implicitly cast to the $(I EnumBaseType). ) $(DDOC_BLANKLINE ) $(CCODE enum S : byte { A }; _Static_assert(sizeof(A) == 1, "A should be size 1"); ) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 register, Register Storage Class)

$(DDOC_BLANKLINE ) $(P Objects with register storage class are treated as auto declarations.) $(DDOC_BLANKLINE ) $(P Objects with register storage class may have their address taken. C11 6.3.2.1-2) $(DDOC_BLANKLINE ) $(P Arrays can have register storage class, and may be enregistered by the compiler. C11 6.3.2.1-3) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 typeof, typeof Operator)

$(DDOC_BLANKLINE ) $(P The typeof operator may be used as a type specifier:) $(GRAMMAR $(GNAME type-specifier): $(GNAME typeof-specifier) $(DDOC_BLANKLINE ) $(GNAME typeof-specifier): $(D typeof $(LPAREN)) $(GNAME expression) $(D $(RPAREN )) $(D typeof $(LPAREN)) $(GNAME type-name) $(D $(RPAREN )) ) $(DDOC_BLANKLINE )

$(LNAME2 __import, Import Declarations)

$(DDOC_BLANKLINE ) $(P Modules can be imported with a $(I CImportDeclaration):) $(DDOC_BLANKLINE ) $(GRAMMAR $(GNAME CImportDeclaration): $(D __import) $(GLINK2 module, ImportList) $(D ;) ) $(DDOC_BLANKLINE ) $(P Imports enable ImportC code to directly access D declarations and functions without the necessity of creating a $(TT .h) file representing those declarations. The tedium and brittleness of keeping the $(TT .h) file up-to-date with the D declarations is eliminated. D functions are available to be inlined. ) $(DDOC_BLANKLINE ) $(P Imports also enable ImportC code to directly import other C files without needing to create a .h file for them, either. Imported C functions become available to be inlined. ) $(DDOC_BLANKLINE ) $(P The $(I ImportList) works the same as it does for D.) $(DDOC_BLANKLINE ) $(P The ordering of $(I CImportDeclaration)s has no significance.) $(DDOC_BLANKLINE ) $(P An ImportC file can be imported, the name of the C file to be imported is derived from the module name.) $(DDOC_BLANKLINE ) $(P All the global symbols in the ImportC file become available to the importing module.) $(DDOC_BLANKLINE ) $(P If a name is referred to in the importing file is not found, the global symbols in each imported file are searched for the name. If it is found in exactly one module, that becomes the resolution of the name. If it is found in multiple modules, it is an error.) $(DDOC_BLANKLINE ) $(NOTE Since ImportC has no scope resolution operator, only global symbols can be found, and a qualification cannot be added to specifiy which module a symbols is in.) $(DDOC_BLANKLINE ) $(P Preprocessor symbols in the imported module are not available to the importing module, and preprocessing symbols in the importing file are not available to the imported module.) $(DDOC_BLANKLINE ) $(P A D module can be imported, in the same manner as that of a $(GLINK2 module, ImportDeclaration).) $(DDOC_BLANKLINE ) $(P Imports can be circular.) $(DDOC_BLANKLINE ) $(CCODE __import core.stdc.stdarg; // get D declaration of va_list __import mycode; // import mycode.c $(DDOC_BLANKLINE ) int foo() { va_list x; // picks up va_list from core.stdc.stdarg return 1 + A; // returns 4 }) $(DDOC_BLANKLINE ) $(P $(TT mycode.c) looks like:) $(DDOC_BLANKLINE ) $(CCODE enum E { A = 3; } ) $(DDOC_BLANKLINE ) $(BEST_PRACTICE Avoid using preprocessor $(TT #define)s like $(TT #define A 3). Use the enum form shown in the above example. Prefer $(TT const) declarations over $(TT #define)s. Rewrite function-style preprocessor macros as inline functions. ) $(DDOC_BLANKLINE )

$(LNAME2 controlZ, Control Z is End Of File)

$(DDOC_BLANKLINE ) $(P A control-Z character \x1A in the source text means End Of File.) $(DDOC_BLANKLINE )

$(LNAME2 gnu-clang-extensions, Gnu and Clang Extensions)

$(DDOC_BLANKLINE ) $(P gcc and clang are presumed to have the same behavior w.r.t. extensions, so gcc as used here refers to both.) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 __attribute__, __attribute__ Extensions)

$(DDOC_BLANKLINE ) $(P The following $(LINK2 https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html, __attribute__ extensions):) $(DDOC_BLANKLINE ) $(OL $(LI __attribute__((aligned(N)))) $(LI __attribute__((always_inline))) $(LI __attribute__((deprecated))) $(LI __attribute__((dllexport))) $(LI __attribute__((dllimport))) $(LI __attribute__((naked))) $(LI __attribute__((noinline))) $(LI $(RELATIVE_LINK2 noreturn, __attribute__((noreturn)))) $(LI others are ignored) ) $(DDOC_BLANKLINE )

$(LNAME2 noreturn, __attribute__((noreturn)))

$(DDOC_BLANKLINE ) $(P __attribute__((noreturn)) marks a function as never returning. gcc set this as an attribute of the function, it is not part of the function's type. In D, a function that never returns has the return type $(GLINK2 type, noreturn). The difference can be seen with the code:) $(CCODE attribute((noreturn)) int foo(); size_t x = sizeof(foo()); ) $(P This code is accepted by gcc, but makes no sense for D. Hence, although it works in ImportC, it is not representable as D code, meaning one must use judgement in creating a .di file to interface with C noreturn functions.) $(DDOC_BLANKLINE ) $(P Furthermore, the D compiler takes advantage of noreturn functions by issuing compile time errors for unreachable code. Such unreachable code, however, is valid C11, and the ImportC compiler will accept it.) $(DDOC_BLANKLINE ) $(BEST_PRACTICE C code that uses the noreturn attribute should at the very least set the return type to void.) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 visualc-extensions, Visual C Extensions)

$(DDOC_BLANKLINE ) $(P All the $(RELATIVE_LINK2 digital-mars-extensions, Digital Mars C Extensions).) $(DDOC_BLANKLINE )

$(LNAME2 __stdcall, __stdcall Function Calling Convention)

$(DDOC_BLANKLINE ) $(P __stdcall sets the calling convention for a function to the Windows API calling convention.) $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD int) __stdcall foo($(D_KEYWORD int) x); ) $(DDOC_BLANKLINE )

$(LNAME2 __declspec, __declspec Attribute Extensions)

$(DDOC_BLANKLINE ) $(P The following $(LINK2 https://learn.microsoft.com/en-us/cpp/cpp/declspec?view=msvc-170, __declspec extensions):) $(DDOC_BLANKLINE ) $(OL $(LI __declspec(align(N))) $(LI __declspec(deprecated)) $(LI __declspec(dllexport)) $(LI __declspec(dllimport)) $(LI __declspec(naked)) $(LI __declspec(noinline)) $(LI __declspec(noreturn)) $(LI __declspec(thread)) $(LI others are ignored) ) $(DDOC_BLANKLINE )

$(LNAME2 __pragma, __pragma Attribute Extensions)

$(DDOC_BLANKLINE ) $(P The following $(LINK @ https://learn.microsoft.com/en-us/cpp/preprocessor/pragma-directives-and-the-pragma-keyword?view=msvc-170, __pragma extensions):) $(DDOC_BLANKLINE ) $(OL $(LI __pragma(pack(N))) $(LI others are ignored) ) $(DDOC_BLANKLINE )

$(LNAME2 digital-mars-extensions, Digital Mars C Extensions)

$(DDOC_BLANKLINE )

$(LNAME2 __stdcall, __stdcall Function Calling Convention)

$(DDOC_BLANKLINE )

$(LNAME2 __declspec, __declspec Attribute Extensions)

$(DDOC_BLANKLINE ) $(P The following $(LINK2 https://digitalmars.com/ctg/ctgLanguageImplementation.html#declspec, __declspec extensions):) $(DDOC_BLANKLINE ) $(OL $(LI __declspec(dllexport)) $(LI __declspec(dllimport)) $(LI __declspec(naked)) $(LI __declspec(thread)) ) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 d-side, ImportC from D's Point of View)

$(DDOC_BLANKLINE ) $(P There is no one-to-one mapping of C constructs to D constructs, although it is very close. What follows is a description of how the D side views the C declarations that are imported.) $(DDOC_BLANKLINE )

$(LNAME2 module-name, Module Name)

$(DDOC_BLANKLINE ) $(P The module name assigned to the ImportC file is the filename stripped of its path and extension. This is just like the default module name assigned to a D module that does not have a module declaration.) $(DDOC_BLANKLINE )

$(LNAME2 extern-C, extern (C))

$(DDOC_BLANKLINE ) $(P All C symbols are extern (C).) $(DDOC_BLANKLINE )

$(LNAME2 enums, Enums)

$(DDOC_BLANKLINE ) $(P The C enum:) $(DDOC_BLANKLINE ) $(CCODE enum E { A, B = 2 };) $(DDOC_BLANKLINE ) $(P appears to D code as:) $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD enum) E : $(D_KEYWORD int) { A, B = 2 } $(D_KEYWORD alias) A = E.A; $(D_KEYWORD alias) B = E.B; ) $(DDOC_BLANKLINE ) $(P The .min and .max properties are available:) $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD static) $(D_KEYWORD assert)(E.min == 0 && E.max == 2); ) $(DDOC_BLANKLINE )

$(LNAME2 tag-symbols, Tag Symbols)

$(DDOC_BLANKLINE ) $(P Tag symbols are the identifiers that appear after the struct, union, and enum keywords, (C11 6.7.2.3). In C, they are placed in a different symbol table from other identifiers. This means two different symbols can use the same name:) $(DDOC_BLANKLINE ) $(CCODE int S; struct S { int a, b; }; S = 3; struct S *ps; ) $(DDOC_BLANKLINE ) $(P D does not make this distinction. Given a tag symbol that is the only declaration of an identifier, that's what the D compiler recognizes. Given a tag symbol and a non-tag symbol that share an identifier, the D compiler recognizes the non-tag symbol. This is normally not a problem due to the common C practice of applying typedef, as in:) $(DDOC_BLANKLINE ) $(CCODE typedef struct S { int a, b; } S; ) $(DDOC_BLANKLINE ) $(P The D compiler recognizes the typedef applied to S, and the code compiles as expected. But when typedef is absent, as in:) $(DDOC_BLANKLINE ) $(CCODE int S; struct S { int a, b; }; ) $(DDOC_BLANKLINE ) $(P the most pragmatic workaround is to add a typedef to the C code:) $(DDOC_BLANKLINE ) $(CCODE int S; struct S { int a, b; }; typedef struct S S_t; // add this typedef ) $(DDOC_BLANKLINE ) $(P Then the D compiler can access the struct tag symbol via S_t.) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 wrapping, Wrapping C Code)

$(DDOC_BLANKLINE ) $(P Many difficulties with adapting C code to ImportC can be done without editing the C code itself. Wrap the C code in another C file and then $(CCODE #include) it. Consider the following problematic C file $(TT file.c):) $(DDOC_BLANKLINE ) $(CCODE void func(int *__restrict p); int S; struct S { int a, b; }; ) $(DDOC_BLANKLINE ) $(P The problems are that $(CCODE __restrict) is not a type qualifier recognized by ImportC (or C11), and the struct S is hidden from D by the declaration $(CCODE int S;). To wrap $(TT file.c) with a fix, create the file $(TT file_ic.c) with the contents:) $(DDOC_BLANKLINE ) $(CCODE #define __restrict restrict #include "file.c" typedef struct S S_t; ) $(DDOC_BLANKLINE ) $(P Then, import file_ic; instead of import file;, and use S_t when $(CCODE struct S) is desired.) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 warnings, Warnings)

$(DDOC_BLANKLINE ) $(P Many suspicious C constructs normally cause warnings to be emitted by default by typical compilers, such as:) $(DDOC_BLANKLINE ) $(CCODE int *p = 3; // Warning: integer implicitly converted to pointer) $(DDOC_BLANKLINE ) $(P ImportC does not emit warnings. The presumption is the user will be importing existing C code developed using another C compiler, and it is written as intended. If C11 says it is legal, ImportC accepts it.) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 builtins, $(TT __builtins.di))

$(DDOC_BLANKLINE ) $(P ImportC uses D to implement several features. These are implemented in the file $(LINK2 https://github.com/dlang/dmd/blob/master/druntime/src/__builtins.di, $(TT __builtins.di)) which is automatically imported for every ImportC compilation.) $(DDOC_BLANKLINE )

$(LNAME2 importcpp, ImportC++)

$(DDOC_BLANKLINE ) $(P ImportC will not compile C++ code. For that, use $(TT dpp).) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 other-solutions, Other Solutions)

$(DDOC_BLANKLINE )

$(LNAME2 dpp, dpp by Atila Neves)

$(DDOC_BLANKLINE ) $(P $(LINK2 https://code.dlang.org/packages/dpp/0.2.1, dpp code)) $(DDOC_BLANKLINE ) $(P $(LINK2 https://dlang.org/blog/2019/04/08/project-highlight-dpp/, dpp Article)) $(DDOC_BLANKLINE ) $(P From the Article:) $(DDOC_BLANKLINE )
dpp is a compiler wrapper that will parse a D source file with the .dpp extension and expand in place any #include directives it encounters, translating all of the C or C++ symbols to D, and then pass the result to a D compiler (DMD by default).
$(DDOC_BLANKLINE ) $(P Like DStep, dpp relies on libclang.) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 dstep, DStep by Jacob Carlborg)

$(DDOC_BLANKLINE ) $(P $(LINK2 https://code.dlang.org/packages/dstep, DStep code)) $(DDOC_BLANKLINE ) $(P $(LINK2 https://dlang.org/blog/2019/04/22/dstep-1-0-0/, DStep Article)) $(DDOC_BLANKLINE ) $(P From the Article:) $(DDOC_BLANKLINE )
DStep is a tool for automatically generating D bindings for C and Objective-C libraries. This is implemented by processing C or Objective-C header files and outputting D modules. DStep uses the Clang compiler as a library (libclang) to process the header files.
$(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 htod, htod by Walter Bright)

$(DDOC_BLANKLINE ) $(P $(LINK2 https://dlang.org/htod.html, htod) converts a C $(TT .h) file to a D source file, suitable for importing into D code. $(B 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 source code for a D module rather than object code.) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 internals, How ImportC Works)

$(DDOC_BLANKLINE ) $(P ImportC's implementation is based on the idea that D's semantics are very similar to C's. ImportC gets its own parser, which converts the C syntax into the same AST (Abstract Syntax Tree) that D uses. The lexer for ImportC is the same as for D, but with some modifications here and there, such as the keywords and integer literals being different. Where the semantics of C differ from D, there are adjustments in the semantic analysis code in the D compiler.) $(DDOC_BLANKLINE ) $(P This co-opting of the D semantic implementation allows ImportC to be able to do things like handle forward references, CTFE (Compile Time Function Execution), and inlining of C functions into D code. Being able to handle forward references means it is not necessary to even write a .h file to be able to import C declarations into D. Being able to perform CTFE is very handy for testing that ImportC is working without needing to generate an executable. But, in general, the strong temptation to add D features to ImportC has been resisted.) $(DDOC_BLANKLINE ) $(P The optimizer and code generator are, of course, the same as D uses.) $(DDOC_BLANKLINE ) $(SPEC_SUBNAV_PREV_NEXT betterc, Better C, ob, Live Functions) ) )