forked from dlang/dlang.org
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathimportc.dd
324 lines (203 loc) · 11 KB
/
importc.dd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
Ddoc
$(SPEC_S ImportC,
$(HEADERNAV_TOC)
$(NOTE This document is under construction. Please excuse the dust and noise.)
$(P 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 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.
)
$(P 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.)
$(P 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.)
$(H2 $(LNAME2 dialect, ImportC Dialect))
$(P There are many versions of C. ImportC is designed to be an
implementation of $(LINK2 https://en.wikipedia.org/wiki/C11_(C_standard_revision), ISO/IEC 9899:2011),
which will hereafter 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.
)
$(P Adjustment to the ImportC dialect is made to match the
behavior of the C compiler that the D compiler is matched to. For
example, on Win32 D is matched to the Digital Mars C compiler,
and can be matched to the Visual C compiler using the $(TT -m32mscoff)
switch. Win64 D is matched to the Visual C compiler.
On Posix targets, the matching C compiler is Gnu C or Clang C.
)
$(P Further adjustment is made to take advantage of some of the D
implementation's capabilities.)
$(P This is all covered in the rest of this document.)
$(H2 $(LNAME2 command-line, Invoking ImportC))
$(P The ImportC compiler can be invoked in two ways:)
$(UL
$(LI directly via the command line)
$(LI indirectly via importing a C file)
)
$(H3 $(LNAME2 command-line, ImportC Files on the Command Line))
$(H3 $(LNAME2 importing, Importing C Files))
$(H2 $(LNAME2 preprocessor, Preprocessor))
$(P ImportC does not have a preprocessor. It is designed to compile C
files after they have been first run through the C preprocessor.)
$(H3 $(LNAME2 spp,Digital Mars C Preprocessor sppn.exe))
$(P $(LINK2 https://www.digitalmars.com/ctg/sc.html, $(TT sppn.exe)) runs on Win32 and is invoked as:)
$(CONSOLE
sppn file.c
)
$(P and the preprocessed output is written to $(TT file.i).)
$(H3 $(LNAME2 gcc-preprocessor, Gnu C Preprocessor))
$(P The $(LINK2 https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html, Gnu C Preprocessor) can be invoked as:)
$(CONSOLE
gcc -E file.c > file.i
)
$(H3 $(LNAME2 clang-preprocessor, Clang C Preprocessor))
$(P The $(LINK2 https://freecompilercamp.org/clang-basics/, Clang Preprocessor) can be invoked as:)
$(CONSOLE
clang -E file.c > file.i
)
$(H3 $(LNAME2 dmpp, dmpp C Preprocessor))
$(P The $(LINK2 https://www.DigitalMars/dmpp, dmpp C Preprocessor) can be invoked as:)
$(CONSOLE
dmpp file.c
)
$(P and the preprocessed output is written to $(TT file.i).)
$(H2 $(LNAME2 preprocessor-directives, Preprocessor Directives))
$(P Nevertheless, ImportC supports these preprocessor directives:)
$(H3 $(LNAME2 line-control, Line control))
$(P C11 6.10.4)
$(H3 $(LNAME2 linemarker, Linemarker))
$(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.)
$(H2 $(LNAME2 limitations, Limitations))
$(H3 $(LNAME2 exceptions, Exception Handling))
$(P ImportC is assumed to never throw exceptions. `setjmp` and `longjmp` are not supported.)
$(H3 $(LNAME2 const, Const))
$(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.)
$(H3 $(LNAME2 volatile, Volatile))
$(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.
)
$(H3 $(LNAME2 restrict, Restrict))
$(P The `restrict` type-qualifier (C11 6.7.3) is ignored.)
$(H3 $(LNAME2 _atomic, _Atomic))
$(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.)
$(H2 $(LNAME2 extensions, Extensions))
$(H3 $(LNAME2 forward-references, Forward References))
$(P Any declarations in scope can be accessed, not just
declarations that lexically precede a reference.)
$(H3 $(LNAME2 ctfe, Compile Time Function Execution))
$(P Evaluating constant expressions includes executing functions in the
same manner as D's CTFE can.)
$(H3 $(LNAME2 inlining, Function Inlining))
$(P Functions for which the function body is present can
be inlined by ImportC as well as by the D code that calls them.)
$(H3 $(LNAME2 register, Register Storage Class))
$(P Objects with `register` storage class are treated as `auto` declarations.)
$(P Objects with `register` storage class may have their address taken. C11 6.3.2.1-2)
$(P Arrays can have `register` storage class, and may be enregistered by the compiler. C11 6.3.2.1-3)
$(H2 $(LNAME2 gnu-clang-extensions, Gnu and Clang Extensions))
$(H2 $(LNAME2 visualc-extensions, Visual C Extensions))
$(H2 $(LNAME2 digital-mars-extensions, Digital Mars C Extensions))
$(H2 $(LNAME2 d-side, ImportC from D's Point of View))
$(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.)
$(H3 $(LNAME2 module-name, Module Name))
$(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.)
$(H3 $(LNAME2 extern-C, `extern (C)`))
$(P All C symbols are `extern (C)`.)
$(H3 $(LNAME2 enums, Enums))
$(P The C enum:)
$(CCODE enum E { A, B = 2 };)
$(P appears to D code as:)
---
enum E : int { A, B = 2 }
alias A = E.A;
alias B = E.B;
---
$(P The `.min` and `.max` properties are available:)
---
static assert(E.min == 0 && E.max == 2);
---
$(H2 $(LNAME2 wrapping, Wrapping C Code))
$(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):)
$(CCODE
void func(int *__restrict p);
int S;
struct S { int a, b; };
)
$(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:)
$(CCODE
#define __restrict restrict
#include "file.c"
typedef struct S S_t;
)
$(P Then, `import file_ic;` instead of `import file;`, and use `S_t` when $(CCODE struct S) is desired.)
$(H2 $(LNAME2 warnings, Warnings))
$(P Many suspicious C constructs normally cause warnings to be emitted by default by
typical compilers, such as:)
$(CCODE int *p = 3; // Warning: integer implicitly converted to pointer)
$(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.)
$(H2 $(LNAME2 importcpp, ImportC++))
$(P ImportC will not compile C++ code. For that, use $(TT dpp).)
$(H2 $(LNAME2 other-solutions, Other Solutions))
$(H3 $(LNAME2 dpp, dpp by Atila Neves))
$(P $(LINK2 https://code.dlang.org/packages/dpp/0.2.1, dpp code))
$(P $(LINK2 https://dlang.org/blog/2019/04/08/project-highlight-dpp/, dpp Article))
$(P From the Article:)
$(BLOCKQUOTE 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).)
$(P Like DStep, dpp relies on libclang.)
$(H3 $(LNAME2 dstep, DStep by Jacob Carlborg))
$(P $(LINK2 https://code.dlang.org/packages/dstep, DStep code))
$(P $(LINK2 https://dlang.org/blog/2019/04/22/dstep-1-0-0/, DStep Article))
$(P From the Article:)
$(BLOCKQUOTE 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.)
$(H3 $(LNAME2 htod, htod by Walter Bright))
$(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.)
$(H2 $(LNAME2 internals, How ImportC Works))
$(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.)
$(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.)
$(P The optimizer and code generator are, of course, the same as D uses.)
$(SPEC_SUBNAV_PREV_NEXT betterc, Better C, ob, Live Functions)
)
Macros:
CHAPTER=41
TITLE=ImportC