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.



Reply via email to