Why using wrappers for D?

Mike Parker via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Oct 3 11:14:11 PDT 2016


On Monday, 3 October 2016 at 17:19:47 UTC, Chalix wrote:

>
> If I "import foo;" in my project, it will be compiled 
> alongside. So there is no need for an extra library. Same 
> should be for wrapfoo.d. If I "import wrapfoo;", I should just 
> need the C-library "foo", and no D-library "food" right?

You do have some confusion here, which Jonathan's answer should 
clear up (that is, importing a module does not cause it to be 
compiled, only makes its symbols to the module in which the 
declaration is made), however, there is one point I'd like to 
make below.

>
> This function wraps the C-like gtk_init function to a D init 
> function.
> The gtk_init function is the function from the GTK+ library, 
> which is loaded in the gtkc/gtk.d file:
>> Linker.link(gtk_init, "gtk_init", LIBRARY.GTK);
> Linker and link are defined in the gtkc/Loader.d
>
> So, why is it not enough just to "import gtk.Main"? What kind 
> of code is inside the gtkd-3 library?

I don't know the details of the gtkd-3 library, but consider this 
example:

```
// csay.c
#include <stdio.h>
void sayHi() { puts("Hi\n"); }

// dsay.d
module dsay;
extern(C) void sayHi();

// hi.d
import dsay;
void main() { sayHi(); }
```

Assuming you have both dmd and dmc installed, you can easily do a 
bit of experimentation like so:

First, use dmd to generate csay.obj.
dmc -c csay.c

Next, with dsay.d, hi.d and csay.obj all in the same directory, 
build an executable.
dmd hi.d csay.obj

This should result in both a successful compile and a successful 
link. But understand that dsay.d was *never* compiled in this 
process. Importing dsay made the source symbol 'sayHi' available 
to hi.d. The compiler emitted a call to sayHi in the generated 
binary (hi.obj). Finally, the linker was able to match that call 
to the C sayHi function and could perform the link to generate 
the executable. Because the binary symbol for sayHi was already 
present in csay.obj, you did not need to compile and link dsay.d.

Now, let's change it up a bit:

```
// csay.h
extern void sayHi();
#define sayHiTwice \
    sayHi(); \
    sayHi();
```

This is a horrible macro, but it serves its purpose as an 
example. In order to provide sayHiTwice in D, it will have to be 
implemented and not just declared:

```
// dsay.d
extern(C) void sayHi();
void sayHiTwice() {
    sayHi();
    sayHi();
}
```

Since the C version of sayHiTwice is a macro and not a function, 
it need not be extern(C). However, no we have an implementation 
and not simply a declaration. So this:

```
// hi.d
import dsay;
void main() { sayHiTwice(); }
```

dmd hi.d csay.obj

Is now going to generate a *linker* error. It will *compile* just 
fine, since the import of dsay makes sayHiTwice visible during 
compilation. However, since csay.obj does not contain a binary 
symbol for sayHiTwice (as it's a macro and not a function), the 
the linker will be unable to match the call to any existing 
symbol and will produce an error. So you would have to do this:

dmd hi.d dsay.d csay.obj

Now, the binary symbol for sayHiTwice will be generated because 
dsay.d is being compiled and linked into the program.

So, when you have a declarations-only module, with no function 
implementations or template instantiations, then it need not 
actually be compiled and linked into the program. In that you are 
correct. But, no, importing a module does not automatically 
compile it. And any function declarations still need an 
implementation somewhere if they are used in the modules you do 
compile.





More information about the Digitalmars-d-learn mailing list