D Programming Language tips

This page is meant to keep a bunch of little tips and answers to FAQs in one place.

See also my D code page when it exists (coming when I have the time) for libraries and examples that I hope will be useful.

  1. How do I easily search the D spec or libraries?
  2. Is there an easy way to use D on linux?
  3. How do I call my C functions from D?

How do I easily search the D spec or libraries?

Daniel Keep explains how to use Google to get good results:

To search for "pure functions" only within the spec and standard library:

pure functions site:digitalmars.com inurl:/d/2

Note that this includes the various articles as well. If you want to exclude Phobos, drop a -inurl:/phobos/ on the end.

Is there an easy way to use D on linux?

Yup. Make helper scripts in /usr/bin that call dmd in a location. Then just unzip dmd into that location and use it. Don't mess with copying stuff to /etc or /lib or whatever - none of that is necessary.

Two posts I wrote to the newsgroup follow, where I explain some details:

On Sun, Mar 01, 2009 at 02:43:08PM +0200, Georg Wrede wrote:
 > I suspect there are some real or perceived difficulties with this? But
 > that's why we have this newsgroup. This embarrasment simply has to go away.
 
 On my system, I don't actually 'install' it; I unzip it and run it
 from that directory (actually I put a script to run it in my PATH, but
 I don't move the executable at all). If that directory is private, it
 is a one user install. If it is public, it works for everyone.
 
 It just works, even for version 1 and 2 at the same time.
 Haven't tried the newest releases yet so it might be
 broken, but I never understand why people have so many problems with this.

And a follow up post by me. Here, I also explain how to easily make Windows .exes from Linux:

On Sun, Mar 01, 2009 at 05:37:05PM +0200, Georg Wrede wrote:
 > This looks excellent!
 >
 > So it's just the docs?
 
 Yeah, the docs are overcomplicated. (I have to admit I never read them;
 I just did the same thing I've been doing with dmc for years and it worked.)
 
 Let me do a 'clean' install of the new version and record my steps here.
 The goal: have dmd for D 1 and D 2 both working at the same time for native
 binaries.
 
 Secondary goal (something else I have working here): have the Windows dmd
 working under Wine for building Windows exes from Linux.
 
 
 
 First, I download the dmd zip files (I always get them from the changelog page.)
 
 To have both 1.0 and 2.0 side by side, we'll make different directories for
 them and put the respective zip file in that directory:
 
 mkdir d2
 mv dmd.2* d2
 mkdir d1
 mv dmd.1* d1
 
 Go in and unzip it:
 
 cd d2
 unzip dmd.2*
 
 Change the permissions (actually optional, see the end of this message for an
 alternative):
 
 cd dmd/linux/bin
 chmod +x dmd
 chmod +x dumpobj
 chmod +x obj2asm
 chmod +x rdmd
 
 
 Now, it works, but we want it in our path. To do this, I just stick a script
 in my path:
 
 Create a file: /usr/bin/dmd with the contents:
 ==========
 #!/bin/bash
 
 /path/to/your/download/folder/d2/dmd/linux/bin/dmd $*
 ==========
 Make it executable:
 chmod +x /usr/bin/dmd
 
 And boom, you can now run:
 
 dmd test.d
 
 And it works correctly.
 
 
 Repeat the process for the D1 download, but call your convenience script
 something else. I personally use /usr/bin/dmd-1.0 but you can do whatever
 you want.
 
 Now:
 dmd test.d
 It works!
 
 dmd-1.0 testv1.d
 It works too!
 
 What about making Windows binaries?
 
 It is trivial:
 
 wine /path/to/your/download/d2/dmd/windows/bin/dmd.exe test.d
 
 Boom, it worked too! Again, you might want a convenience script:
 
 /usr/bin/dmd-win
 =========
 #!/bin/bash
 
 wine /path/to/your/download/d2/dmd/windows/bin/dmd.exe $*
 =========
 
 (And repeat for D1.) And now you can make Linux or Windows binaries with D1
 or D2, all side by side, all with ease.
 
 
 When you want to update your compiler, simply grab the new zip in the same
 download folder, unzip it, overwriting the old ones, chmod +x linux/bin/dmd,
 and have fun.
 
 
 Btw, if chmoding it every time is too much of a hassle, your convenience
 scripts can render that unneeded too.
 
 Just use
 
 ========
 /bin/bash
 
 /lib/ld-linux.so.2 /path/to/your/download/d2/dmd/linux/bin/dmd $*
 ==========
 
 Instead. Thus you don't need to chmod +x the file from the zip.
 
 If you go that way, updating your compiler is as simple as downloading
 the new zip and unzipping it over your old install.
 
 
 
 For a private install, just put your convenience scripts somewhere in your
 home dir and add them to your path.
 
 For a public install, make sure your download directory is world readable.

 

How do I call C functions from D?

Make an extern (C) { } in your D file where you list the prototypes to the C functions you are interested in. Compile the C file separately, then add the object file from that to your dmd command line. You can now call the C functions.

Here is a post I wrote to the newsgroup showing an example:

If your main() is in the D file, it is really easy:

====== file.c ==========

extern int globalFromD;

void functionFromC(int a) {
   globalFromD = a;
}

======= code.d ==========

extern(C) { // this is needed to make it available from C
        __gshared int globalFromD; 
			// note the gshared is needed in more recent
			// versions of D2 because of the shift to thread
			// local storage, which C doesn't expect.
}
extern(C) { // also needed when listing the prototypes for your C functions
        void functionFromC(int);
}

import std.stdio; // for writefln

int main() {
        globalFromD = 100;
        writefln("%d", globalFromD);

        functionFromC(500);
        writefln("%d", globalFromD);

        return 0;
}

=====================
To compile them (assuming linux):

gcc -c file.c
dmd code.d file.o


In general: compile your C file separately, then add the object file from
that on to the end of the dmd command line.

Run the program:

./code
100
500

---------
Some of the types in the prototypes listed in the D file might change a bit.
This is where htod comes in to help. Or you could do the hackish thing I
often do and just list void* for all pointers. The fun comes in with
accessing C structs. For them, you need to copy/paste and fix the syntax
of the struct definition into the extern(C) block.

But if your C functions just take pointers to structs, you can

typedef void* StructName;

in the D and still pass it around. You can't access the members directly,
but I find this is often good enough.

Anyway, this extern(C) block of the prototypes is what htod automates, so
you might not need to worry about this, just

import file; // where file is the .d file the htod spits out

and start calling your functions. Remember to stick the object file from
compiling the .c on the dmd command line though or you'll get linker errors.


======

If your main() is in the C file, things get messier, since you need to
set up exceptions and the runtime and whatnot. I don't know the process
for that off the top of my head.

By Adam D. Ruppe. I release this document into the public domain.

Last edited: May 16, 2009