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