This shows you the differences between two versions of the page.
|
dss:laboratoare:07 [2019/07/03 15:28] razvan.nitu1305 |
dss:laboratoare:07 [2021/07/19 10:08] (current) razvan.nitu1305 [Vibe.d] |
||
|---|---|---|---|
| Line 97: | Line 97: | ||
| === Accessing C globals === | === Accessing C globals === | ||
| - | C globals can be accessed directly from D. C globals have the C naming convention, and so must be in an **extern (C)** block. Use the **extern** storage class to indicate that the global is allocated in the C code, not the D code. C globals default to being in global, not thread local, storage. To reference global storage from D, use the **__gshared** storage class. | + | C globals can be accessed directly from D. C globals have the C naming convention, and so must be in an **extern (C)** block. Use the **extern** storage class to indicate that the global is allocated in the C code, not the D code. C globals default to being in global, not thread local, storage. To reference global storage from D, use the **gshared** storage class. |
| <code D> | <code D> | ||
| Line 137: | Line 137: | ||
| Note that all instantiations used in D code must be provided by linking to C++ object code or shared libraries containing the instantiations. | Note that all instantiations used in D code must be provided by linking to C++ object code or shared libraries containing the instantiations. | ||
| + | |||
| + | ==== BetterC ==== | ||
| + | |||
| + | It is straightforward to link C functions and libraries into D programs. But linking D functions and libraries into C programs is not straightforward. | ||
| + | |||
| + | D programs generally require: | ||
| + | |||
| + | - The D runtime library to be linked in, because many features of the core language require runtime library support. | ||
| + | - The **main()** function to be written in D, to ensure that the required runtime library support is properly initialized. | ||
| + | |||
| + | To link D functions and libraries into C programs, it's necessary to only require the C runtime library to be linked in. This is accomplished by defining a subset of D that fits this requirement, called BetterC. BetterC is typically enabled by setting the -betterC command line flag for the implementation. | ||
| + | |||
| + | D features not available with BetterC: | ||
| + | |||
| + | * Garbage Collection | ||
| + | * TypeInfo and ModuleInfo | ||
| + | * Classes | ||
| + | * Built-in threading (e.g. core.thread) | ||
| + | * Dynamic arrays (though slices of static arrays work) and associative arrays | ||
| + | * Exceptions | ||
| + | * synchronized and core.sync | ||
| + | * Static module constructors or destructors | ||
| + | * Vector Extensions | ||
| + | |||
| + | ==== Dub ==== | ||
| + | |||
| + | Dub is a package and build manager for D applications and libraries. | ||
| + | |||
| + | For a dub tutorial, visit this [[https://dub.pm/|page]]. | ||
| + | |||
| + | ==== DPP ==== | ||
| + | |||
| + | D was designed from the beginning to be ABI compatible with C. Translate the declarations from a C header file into a D module and you can link directly with the corresponding C library or object files. The same is true in the other direction as long as the functions in the D code are annotated with the appropriate linkage attribute. These days, it’s possible to bind with C++ and even Objective-C. | ||
| + | |||
| + | 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). Example: | ||
| + | |||
| + | <code D> | ||
| + | // stdlib.dpp | ||
| + | #include <stdio.h> | ||
| + | #include <stdlib.h> | ||
| + | |||
| + | void main() { | ||
| + | printf("Hello world\n".ptr); | ||
| + | |||
| + | enum numInts = 4; | ||
| + | auto ints = cast(int*) malloc(int.sizeof * numInts); | ||
| + | scope(exit) free(ints); | ||
| + | |||
| + | foreach(int i; 0 .. numInts) { | ||
| + | ints[i] = i; | ||
| + | printf("ints[%d]: %d ".ptr, i, ints[i]); | ||
| + | } | ||
| + | |||
| + | printf("\n".ptr); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | |||
| + | |||
| + | ===== Exercises ==== | ||
| + | |||
| + | ==== 1. C function interface ==== | ||
| + | |||
| + | - Write a D function that computes the average of an array of ints. | ||
| + | - Write a main function in C that calls the function previously defined. | ||
| + | - Compile the code. Does it work? Why? | ||
| + | |||
| + | <note hint> | ||
| + | How are arrays represented in D? But in C? | ||
| + | </note> | ||
| + | |||
| + | ==== 2. C struct interface ==== | ||
| + | |||
| + | - Write a C function, called **sumMembers** that receives a parameter of type **struct List3** that packs 3 integer values and computes the sum of the 3 members. Define struct Node and a main function that calls **sumMembers**. | ||
| + | - Reimplement **sumMembers** in D by cut-pasting the original code. When linking the objects try using both **gcc** and **dmd**. What happens? | ||
| + | - Redesign **sumMembers** by initializing a builtin array from the members and calling the library function [[https://dlang.org/phobos/std_algorithm_iteration.html#sum|sum]] on it. Before calling sum, manually add 5 and 6 to the array by using the concatenation equals operator "~=". When linking, try using both **gcc** and **dmd**. What happens? Why? | ||
| + | - Compile the D code with betterC. What happens? Why? | ||
| + | |||
| + | ==== 3. Dub ==== | ||
| + | |||
| + | Clone [[https://github.com/libmir/mir|this repo]]. That is a competing library of phobos. Build, run and test the program using dub. | ||
| + | |||
| + | ==== 4. DPP ==== | ||
| + | |||
| + | Install dpp by using dub: | ||
| + | |||
| + | <code bash> | ||
| + | sudo apt-get install libclang1-3.9 libclang-3.9-dev | ||
| + | dub fetch libclang | ||
| + | dub build libclang | ||
| + | dub fetch dpp | ||
| + | dub build dpp | ||
| + | </code> | ||
| + | |||
| + | dpp will be installed in **~/.dub/packages/dpp-some-version**. You should probably create an alias with the executable. | ||
| + | |||
| + | Write a D program of your choosing in which you use C-style **include** directives. Compile and run the program with dpp. | ||