Building and Using DLLs
Prev | Chapter 4. Programming with Cygwin | Next

## Building and Using DLLs

DLLs are Dynamic Link Libraries, which means that they're linked into your program at run time instead of build time. There are three parts to a DLL:

- the exports

- the code and data

- the import library

The code and data are the parts you write - functions, variables, etc. All these are merged together, like if you were building one big object files, and put into the dll. They are not put into your .exe at all.

The exports is a list of functions and variables that the dll makes available to other programs. Think of this as the list of "public" symbols, the rest being hidden. [1] This list can be in a module definition (.def) file, which you can write by hand with a text editor, but it's also possible to have it generated automatically from the functions and variables in your code, by annotating the declarations with `__attribute__ ((dllexport))`. [2]

The import library is a regular UNIX-like `.a` library, but it only contains the tiny bit of information ("a stub") needed to tell the OS how your program interacts with ("imports") the dll. This information is linked into your `.exe`.

Refer to the section of the ld manual discussing Win32 PE specifics for more details.

### Building DLLs

This page gives only a few simple examples of gcc's DLL-building capabilities. To begin an exploration of the many additional options, see the gcc documentation and website, currently at http://gcc.gnu.org/

Let's go through a simple example of how to build a dll. For this example, we'll use a single file `myprog.c` for the program (`myprog.exe`) and a single file `mydll.c` for the contents of the dll (`mydll.dll`).

Say you want to build this minimal function in `mydll.c`:

    #include <stdio.h>

    int
    hello()
    {
      printf ("Hello World!\n");
    }

First compile `mydll.c` to the object `mydll.o`:

    gcc -c mydll.c

Then, tell gcc that it is building a shared library:

    gcc -shared -o mydll.dll mydll.o -Wl,--out-implib libmydll.a

That's it! You now have the dll (`mydll.dll`) and the import library (`libmydll.a`). [3]

To finish up the example, you can now link to the dll with a simple program, `myprog.c`:

    int
    main ()
    {
      hello ();
    }

Then link to your dll with a command like:

    gcc -o myprog myprog.c -L./ -lmydll

Try it out:

    $ ./myprog
    Hello World!

However, if you are building a dll for installation, you will probably want to use a more complex syntax:

    gcc -shared -o cyg${module}.dll \
        -Wl,--out-implib=lib${module}.dll.a \
        -Wl,--whole-archive ${objs_libs} -Wl,--no-whole-archive \
        ${dependency_libs}

- The name of your library is `${module}`, prefixed with `cyg` for the DLL and `lib` for the import library. Cygwin DLLs use the `cyg` prefix to differentiate them from native-Windows MinGW DLLs.
- `${objs_libs}` are all your object files, bundled together in static libs or single object files
- `${dependency_libs}` are static or import libs you need to link against, e.g `'-lpng -lz -L/usr/local/special -lmyspeciallib'` .

When the import library is installed into `/usr/lib`, it can be linked to with just `-l${module}`. The dll itself is installed into `/usr/bin` so it can be found on `PATH` by the loader when a linked .exe is run.

### dlltool

Historically, the process for building a dll with `gcc` and `binutils` wasn't so simple, and the `dlltool` tool was used:

- To create the exports section of the dll, from the module definition file or by scanning object files.

- To generate the import library.

(See the `dlltool` man page for more details.)

### Linking Against Foreign DLLs

If you have an existing DLL already, you need to build a Cygwin-compatible import library. If you have the source to compile the DLL, see the section called “Building DLLs” for details on having `gcc` build one for you. If you do not have the source or a supplied working import library, you can get most of the way by creating a .def file with these commands (you might need to do this in `bash` for the quoting to work correctly):

    echo EXPORTS > foo.def
    nm foo.dll | grep ' T _' | sed 's/.* T _//' >> foo.def

Note that this will only work if the DLL is not stripped. Otherwise you will get an error message: "No symbols in foo.dll".

Once you have the `.def` file, you can create an import library from it like this:

    dlltool --def foo.def --dllname foo.dll --output-lib foo.a

[1] Note that `ld`'s default behaviour is to export all global symbols, if there otherwise wouldn't be any exported symbols (i.e. because you haven't specified a def file or made any export annotations). (See `--export-all-symbols` in the `ld` man page for more details.)

[2] If you're making these annotations on the declarations in a header which is also installed to be included by users of your library, you probably want to use macros to do the right thing and increase portability. See this example for details.

[3] In fact, `--out-implib` is optional in this simple example, because `ld` can automatically generate import stubs when told to link directly to a .dll. (See `--enable-auto-import` in the `ld` man page for more details.)

Prev | Up | Next
Debugging Cygwin Programs | Home | Defining Windows Resources