ImportC - D Programming Language
Description: D Programming Language
Keywords: D programming language

Menu

- Learn
- Documentation
  - Language Reference
  - Library Reference
  - Command-line Reference
  - Feature Overview
  - Articles
- Downloads
- Packages
- Community
  - Blog
  - Orgs using D
  - Twitter
  - Calendar
  - Forums
  - IRC
  - Community Discord
  - Wiki
  - GitHub
  - Issues
  - Get involved
  - Contributors
  - Foundation
  - Security Team
  - Donate
  - Sponsors
- Resources
  - Tour
  - Books
  - Tutorials
  - Tools
  - Editors
  - IDEs
  - run.dlang.io
  - Visual D
  - Acknowledgments
  - D Style
  - Glossary
  - Sitemap

Search
Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

# ImportC

Contents

1. ImportC Dialect
2. Invoking ImportC
   1. ImportC Files on the Command Line
   2. Importing C Files
3. Preprocessor
   1. Digital Mars C Preprocessor sppn.exe
   2. Gnu C Preprocessor
   3. Clang C Preprocessor
   4. dmpp C Preprocessor
4. Predefined Macros
5. Preprocessor Directives
   1. Line control
   2. Linemarker
6. Implementation
   1. Enums
   2. Bit Fields
   3. Implicit Function Declarations
   4. #pragma STDC FENV_ACCESS
7. Limitations
   1. Exception Handling
   2. Const
   3. Volatile
   4. Restrict
   5. _Atomic
   6. Compatible Types
   7. Same only Different Types
   8. _Generic
8. Extensions
   1. Forward References
   2. Compile Time Function Execution
   3. Function Inlining
   4. Enum Base Types
   5. Register Storage Class
9. Gnu and Clang Extensions
   1. __attribute__((noreturn))
10. Visual C Extensions
11. Digital Mars C Extensions
12. ImportC from D's Point of View
    1. Module Name
    2. extern (C)
    3. Enums
13. Wrapping C Code
14. Warnings
15. ImportC++
16. Other Solutions
    1. dpp by Atila Neves
    2. DStep by Jacob Carlborg
    3. htod by Walter Bright
17. How ImportC Works

Note: This document is under construction. Please excuse the dust and noise.

ImportC is a C compiler embedded into the D implementation. Its purpose is to enable direct importation of C files, without needing to manually prepare a D file corresponding to the declarations in the C file. It enables directly compiling C files into modules, and linking them in with D code to form an executable. It can be used as a C compiler to compile and link 100% C programs.

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.

ImportC and 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.

## ImportC Dialect

There are many versions of C. ImportC is designed to be an implementation of ISO/IEC 9899:2011, which will hereafter be referred to as 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.

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 associated C compiler. For example, on Win32 D is matched to the Digital Mars C compiler, and can be matched to the Visual C compiler using the -m32mscoff switch. Win64 D is matched to the Visual C compiler. On Posix targets, the matching C compiler is Gnu C or Clang C.

Further adjustment is made to take advantage of some of the D implementation's capabilities.

This is all covered in the rest of this document.

## Invoking ImportC

The ImportC compiler can be invoked in two ways:

- directly via the command line
- indirectly via importing a C file

### ImportC Files on the Command Line

### Importing C Files

## Preprocessor

ImportC does not have a preprocessor. It is designed to compile C files after they have been first run through the C preprocessor.

### Digital Mars C Preprocessor sppn.exe

sppn.exe runs on Win32 and is invoked as:

        sppn file.c

and the preprocessed output is written to file.i.

### Gnu C Preprocessor

The Gnu C Preprocessor can be invoked as:

        gcc -E file.c > file.i

### Clang C Preprocessor

The Clang Preprocessor can be invoked as:

        clang -E file.c > file.i

### dmpp C Preprocessor

The dmpp C Preprocessor can be invoked as:

        dmpp file.c

and the preprocessed output is written to file.i.

## Predefined Macros

ImportC does not predefine any macros.

Best Practices: To distinguish an ImportC compile vs some other C compiler, define __IMPORTC__ to be 1 when the preprocessor is run.

## Preprocessor Directives

Nevertheless, ImportC supports these preprocessor directives:

### Line control

C11 6.10.4

### Linemarker

linemarker directives are normally embedded in the output of C preprocessors.

## Implementation

The implementation defined characteristics of ImportC are:

### Enums

enumeration-constants are always typed as int.

The expression that defines the value of an enumeration-constant must be an integral type and evaluate to an integer value that fits in an int.

    enum E { -10, 0x81231234 }; // ok
    enum F {  0x812312345678 }; // error, doesn't fit in int
    enum G { 1.0 };             // error, not integral type

The enumerated type is int.

### Bit Fields

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

### Implicit Function Declarations

Implicit function declarations:

        int main()
        {
            func();  // implicit declaration of func()
        }

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.

Rationale: Implicit function declarations are very error-prone and cause hard to find bugs.

### #pragma STDC FENV_ACCESS

This is described in C11 7.6.1

    #pragma STDC FENV_ACCESS on-off-switch

    on-off-switch:
        ON
        OFF
        DEFAULT

It is completely ignored.

## Limitations

### Exception Handling

ImportC is assumed to never throw exceptions. setjmp and longjmp are not supported.

### Const

C11 specifies that const only applies locally. const in ImportC applies transitively, meaning that although

    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.

### Volatile

The volatile type-qualifier (C11 6.7.3) is ignored. Use of volatile to implement shared memory access is unlikely to work anyway, _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.

### Restrict

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

### _Atomic

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.

### Compatible Types

Compatible Types (C11 6.7.2) are identical types in ImportC.

### Same only Different Types

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.

### _Generic

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

## Extensions

### Forward References

Any declarations in scope can be accessed, not just declarations that lexically precede a reference.

### Compile Time Function Execution

Evaluating constant expressions includes executing functions in the same manner as D's CTFE can.

### Function Inlining

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

### Enum Base Types

Enums are extended with an optional EnumBaseType:

    EnumDeclaration:
        enum Identifier : EnumBaseType EnumBody

    EnumBaseType:
        Type

which, when supplied, causes the enum members to be implicitly cast to the EnumBaseType.

    enum S : byte { A };
    _Static_assert(sizeof(A) == 1, "A should be size 1");

### Register Storage Class

Objects with register storage class are treated as auto declarations.

Objects with register storage class may have their address taken. C11 6.3.2.1-2

Arrays can have register storage class, and may be enregistered by the compiler. C11 6.3.2.1-3

## Gnu and Clang Extensions

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

### __attribute__((noreturn))

__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 noreturn. The difference can be seen with the code:

        attribute((noreturn)) int foo();
        size_t x = sizeof(foo());

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.

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.

Best Practices: C code that uses the noreturn attribute should at the very least set the return type to void.

## Visual C Extensions

## Digital Mars C Extensions

## ImportC from D's Point of View

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.

### Module Name

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.

### extern (C)

All C symbols are extern (C).

### Enums

The C enum:

    enum E { A, B = 2 };

appears to D code as:

    enum E : int { A, B = 2 }
    alias A = E.A;
    alias B = E.B;

The .min and .max properties are available:

    static assert(E.min == 0 && E.max == 2);

## Wrapping C Code

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

    #include

it. Consider the following problematic C file file.c:

        void func(int *__restrict p);
        int S;
        struct S { int a, b; };

The problems are that

    __restrict

is not a type qualifier recognized by ImportC (or C11), and the struct S is hidden from D by the declaration

    int S;

. To wrap file.c with a fix, create the file file_ic.c with the contents:

        #define __restrict restrict
        #include "file.c"
        typedef struct S S_t;

Then, import file_ic; instead of import file;, and use S_t when

    struct S

is desired.

## Warnings

Many suspicious C constructs normally cause warnings to be emitted by default by typical compilers, such as:

    int *p = 3; // Warning: integer implicitly converted to pointer

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.

## ImportC++

ImportC will not compile C++ code. For that, use dpp.

## Other Solutions

### dpp by Atila Neves

dpp code

dpp Article

From the Article:

> 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).

Like DStep, dpp relies on libclang.

### DStep by Jacob Carlborg

DStep code

DStep Article

From the Article:

> 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.

### htod by Walter Bright

htod converts a C .h file to a D source file, suitable for importing into D code. 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.

## How ImportC Works

This is a description of how ImportC is implemented, intended to remove the mystery of various design choices.

Better C
Live Functions
Copyright © 1999-2022 by the D Language Foundation | Page generated by Ddoc on Thu Apr 7 14:47:15 2022