2000-02-18 03:38:33 +08:00
|
|
|
<sect1 id="dll"><title>Building and Using DLLs</title>
|
|
|
|
|
|
|
|
<para>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:</para>
|
|
|
|
|
|
|
|
<itemizedlist spacing="compact">
|
|
|
|
<listitem><para> the exports </para></listitem>
|
|
|
|
<listitem><para> the code and data </para></listitem>
|
|
|
|
<listitem><para> the import library </para></listitem>
|
|
|
|
</itemizedlist>
|
|
|
|
|
|
|
|
<para>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.</para>
|
|
|
|
|
|
|
|
<para>The exports contains a list of functions and variables that the
|
|
|
|
dll makes available to other programs. Think of this as the list of
|
|
|
|
"global" symbols, the rest being hidden. Normally, you'd create this
|
|
|
|
list by hand with a text editor, but it's possible to do it
|
|
|
|
automatically from the list of functions in your code. The
|
|
|
|
<filename>dlltool</filename> program creates the exports section of
|
|
|
|
the dll from your text file of exported symbols.</para>
|
|
|
|
|
|
|
|
<para>The import library is a regular UNIX-like
|
|
|
|
<filename>.a</filename> library, but it only contains the tiny bit of
|
|
|
|
information needed to tell the OS how your program interacts with
|
|
|
|
("imports") the dll. This information is linked into your
|
|
|
|
<filename>.exe</filename>. This is also generated by
|
|
|
|
<filename>dlltool</filename>.</para>
|
|
|
|
|
|
|
|
<sect2 id="dll-build"><title>Building DLLs</title>
|
|
|
|
|
2003-02-03 08:30:45 +08:00
|
|
|
<para>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
|
2004-12-25 05:58:38 +08:00
|
|
|
<ulink url="http://gcc.gnu.org/">http://gcc.gnu.org/</ulink>
|
2004-01-24 16:09:45 +08:00
|
|
|
</para>
|
2003-02-03 08:30:45 +08:00
|
|
|
|
|
|
|
<para>Let's go through a simple example of how to build a dll.
|
2000-02-18 03:38:33 +08:00
|
|
|
For this example, we'll use a single file
|
|
|
|
<filename>myprog.c</filename> for the program
|
|
|
|
(<filename>myprog.exe</filename>) and a single file
|
|
|
|
<filename>mydll.c</filename> for the contents of the dll
|
|
|
|
(<filename>mydll.dll</filename>).</para>
|
|
|
|
|
2002-08-21 23:45:04 +08:00
|
|
|
<para>Fortunately, with the latest gcc and binutils the process for building a dll
|
2002-08-22 00:02:17 +08:00
|
|
|
is now pretty simple. Say you want to build this minimal function in mydll.c:</para>
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2002-10-23 11:55:34 +08:00
|
|
|
<screen>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
int
|
|
|
|
hello()
|
2002-08-21 23:45:04 +08:00
|
|
|
{
|
2002-10-23 11:55:34 +08:00
|
|
|
printf ("Hello World!\n");
|
|
|
|
}
|
|
|
|
</screen>
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2002-08-21 23:45:04 +08:00
|
|
|
<para>First compile mydll.c to object code:</para>
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2002-08-21 23:45:04 +08:00
|
|
|
<screen>gcc -c mydll.c</screen>
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2002-08-21 23:45:04 +08:00
|
|
|
<para>Then, tell gcc that it is building a shared library:</para>
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2002-08-21 23:45:04 +08:00
|
|
|
<screen>gcc -shared -o mydll.dll mydll.o</screen>
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2002-10-23 11:55:34 +08:00
|
|
|
<para>
|
|
|
|
That's it! To finish up the example, you can now link to the
|
|
|
|
dll with a simple program:
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<screen>
|
|
|
|
int
|
|
|
|
main ()
|
|
|
|
{
|
|
|
|
hello ();
|
|
|
|
}
|
|
|
|
</screen>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Then link to your dll with a command like:
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<screen>gcc -o myprog myprog.ca -L./ -lmydll</screen>
|
|
|
|
|
|
|
|
<para>However, if you are building a dll as an export library,
|
2002-08-21 23:45:04 +08:00
|
|
|
you will probably want to use the complete syntax:</para>
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2002-08-21 23:45:04 +08:00
|
|
|
<screen>gcc -shared -o cyg${module}.dll \
|
|
|
|
-Wl,--out-implib=lib${module}.dll.a \
|
|
|
|
-Wl,--export-all-symbols \
|
|
|
|
-Wl,--enable-auto-import \
|
2004-01-11 16:32:09 +08:00
|
|
|
-Wl,--whole-archive ${old_libs} \
|
2002-08-21 23:45:04 +08:00
|
|
|
-Wl,--no-whole-archive ${dependency_libs}</screen>
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2004-01-11 16:32:09 +08:00
|
|
|
<para>
|
|
|
|
The name of your library is <literal>${module}</literal>, prefixed with
|
|
|
|
<literal>cyg</literal> for the DLL and <literal>lib</literal> for the
|
|
|
|
import library. Cygwin DLLs use the <literal>cyg</literal> prefix to
|
|
|
|
differentiate them from native-Windows MinGW DLLs, see
|
2004-12-25 05:58:38 +08:00
|
|
|
<ulink url="http://mingw.org">the MinGW website</ulink> for more details.
|
2004-01-11 16:32:09 +08:00
|
|
|
<literal>${old_libs}</literal> are all
|
2002-08-21 23:45:04 +08:00
|
|
|
your object files, bundled together in static libs or single object
|
2004-01-11 16:32:09 +08:00
|
|
|
files and the <literal>${dependency_libs}</literal> are import libs you
|
|
|
|
need to link against, e.g
|
|
|
|
<userinput>'-lpng -lz -L/usr/local/special -lmyspeciallib'</userinput>.
|
|
|
|
</para>
|
2000-02-18 03:38:33 +08:00
|
|
|
</sect2>
|
|
|
|
|
|
|
|
<sect2 id="dll-link"><title>Linking Against DLLs</title>
|
|
|
|
|
|
|
|
<para>If you have an existing DLL already, you need to build a
|
2002-10-23 11:55:34 +08:00
|
|
|
Cygwin-compatible import library. If you have the source to compile
|
2004-12-25 05:58:38 +08:00
|
|
|
the DLL, see <xref linkend="dll-build"></xref> for details on having
|
2002-10-23 11:55:34 +08:00
|
|
|
<filename>gcc</filename> build one for you. If you do not have the
|
|
|
|
source or a supplied working import library, you can get most of
|
2000-02-18 03:38:33 +08:00
|
|
|
the way by creating a .def file with these commands (you might need to
|
|
|
|
do this in <filename>bash</filename> for the quoting to work
|
|
|
|
correctly):</para>
|
|
|
|
|
|
|
|
<screen>
|
|
|
|
echo EXPORTS > foo.def
|
|
|
|
nm foo.dll | grep ' T _' | sed 's/.* T _//' >> foo.def
|
|
|
|
</screen>
|
|
|
|
|
|
|
|
<para>Note that this will only work if the DLL is not stripped.
|
|
|
|
Otherwise you will get an error message: "No symbols in
|
|
|
|
foo.dll".</para>
|
|
|
|
|
|
|
|
<para>Once you have the <filename>.def</filename> file, you can create
|
|
|
|
an import library from it like this:</para>
|
|
|
|
|
|
|
|
<screen>
|
|
|
|
dlltool --def foo.def --dllname foo.dll --output-lib foo.a
|
|
|
|
</screen>
|
|
|
|
|
|
|
|
</sect2>
|
|
|
|
|
|
|
|
</sect1>
|