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