Note: This website is archived. For up-to-date information about D projects and development, please visit

Basic DDL Tutorial

(Back to Tutorials)

In this tutorial you will see examples on how to:

  • Create a plugin
  • Create a host program
  • Load a plugin
  • Execute a method located within a plugin
  • Call host-program methods from a plugin

Source Listing for this tutorial

1. Create a Plugin

Similar to the Quick Tutorial, we're going to use a single D module as our plugin in this example. Do do that, simply create a .d file like so:

module plugin;


void helloWorld(){
    Stdout("hello world"c).newline;

You're only going to need the object file that the compiler creates, so just compile it:

dmd -c examples/basic/plugin.d

The .obj file generated by DMD here is an OMF binary file. We're going to refer to it as a "Plugin" from here on.

Note that the code above doesn't reference DDL at all. It doesn't need to since it's not performing any linking of it's own.

2. Create a Host Program

The host program is going to need to include DDL. This is where the dynamic loading and linking of the plugin is going to take place.

module basic;

import ddl.DefaultRegistry;
import ddl.Linker;


void main(){
    auto linker = new Linker(new DefaultRegistry());

    auto plugin = linker.loadAndLink("plugin.obj");

    auto helloWorld = plugin.getDExport!(void function(),"plugin.helloWorld")();

    Stdout("calling the helloWorld function"c).newline;

Then build the program using build. Be sure to not use the -clean option, as we'll need the .map file (DMD creates one by default) later.

build examples/basic/basic

3. Prep and Execute

Your project directory should now contain quick.exe,, plugin.obj, snn.lib and phobos.lib.

Now run your host program.


This should output the message from your helloWorld() function.

hello world

4. Discussion

This lesson differs from the Quick Tutorial in that the helloWorld() method that is bound at runtime, invokes Stdout itself, rather than passing a string back to the host program.

But the difference is more than in just the code: under the hood, Stdout is actually stored in the host program, not the plugin. If you remove the import for "" and/or the "Stdout(...).newline" call from the host program, and recompile, you'll see that the whole mess fails spectacularly:

Error: cannot resolve symbol: [0] unresolved external _D5tango2io5Print12__T5PrintTaZ5Print7newlineMFZC5tango2io5Print12__T5PrintTaZ5Print

We'll delve into this more in the next tutorial.