This shows you the differences between two versions of the page.
|
dss:laboratoare:07 [2019/07/03 15:15] razvan.nitu1305 |
dss:laboratoare:07 [2021/07/19 10:08] (current) razvan.nitu1305 [Vibe.d] |
||
|---|---|---|---|
| Line 88: | Line 88: | ||
| Both sides need to define the struct in order to know the layout in memory of the fields. | Both sides need to define the struct in order to know the layout in memory of the fields. | ||
| + | |||
| + | === Using existing C libraries === | ||
| + | |||
| + | Since D can call C code directly, it can also call any C library functions, giving D access to the smorgasbord of existing C libraries. To do so, however, one needs to write a D interface (.di) file, which is a translation of the C .h header file for the C library into D. | ||
| + | |||
| + | For popular C libraries, the first place to look for the corresponding D interface file is the [[https://github.com/D-Programming-Deimos/|Deimos Project]]. If it isn't there already, and you write one, please contribute it to the Deimos Project. | ||
| + | |||
| + | === 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. | ||
| + | |||
| + | <code D> | ||
| + | extern (C) __gshared int x; | ||
| + | </code> | ||
| + | |||
| + | ==== Interfacing to C++ ==== | ||
| + | |||
| + | Calling D functions from C++ and viceversa are achieved exactly the same as in the case of C, by using **extern(C++)**. | ||
| + | |||
| + | === C++ namespaces === | ||
| + | |||
| + | C++ symbols that reside in namespaces can be accessed from D. A namespace can be added to the **extern (C++)** linkage attribute: | ||
| + | |||
| + | <code D> | ||
| + | extern (C++, N) int foo(int i, int j, int k); | ||
| + | |||
| + | void main() | ||
| + | { | ||
| + | N.foo(1, 2, 3); // foo is in C++ namespace 'N' | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | === Classes === | ||
| + | |||
| + | C++ classes can be declared in D by using the **extern (C++)** attribute on class, struct and interface declarations. **extern (C++)** interfaces have the same restrictions as D interfaces, which means that Multiple Inheritance is supported to the extent that only one base class can have member fields. | ||
| + | |||
| + | **extern (C++)** structs do not support virtual functions but can be used to map C++ value types. | ||
| + | |||
| + | Unlike classes and interfaces with D linkage, **extern (C++)** classes and interfaces are not rooted in **Object** and cannot be used with **typeid**. | ||
| + | |||
| + | === Structs === | ||
| + | |||
| + | C++ allows a struct to inherit from a base struct. This is done in D using alias this. | ||
| + | |||
| + | === C++ Templates === | ||
| + | |||
| + | C++ function and type templates can be bound by using the **extern (C++)** attribute on a function or type template declaration. | ||
| + | |||
| + | 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. | ||