25.4 DLLs with Libtool
Windows' DLLs, are very different to their nearest equivalent on
Unix: shared libraries. This makes Libtool's job of hiding both
behind the same abstraction extremely difficult -- it is not fully
implemented at the time of writing. As a package author that wants to
use DLLs on Windows with Libtool, you must construct your packages
very carefully to enable them to build and link with DLLs in the
same way that they build and link with shared libraries on Unix.
Some of the difficulties that must be addressed follow:
At link time, a DLL effectively consists of two parts; the DLL
itself which contains the shared object code, and an import library
which consists of the stub(65) functions which are actually
linked into the executable, at a rate of one stub per entry point. Unix
has a run time loader which links shared libraries into the main program
as it is executed, so the shared library is but a single file.
Pointer comparisons do not always work as expected when the pointers
cross a DLL boundary, since you can be comparing the addresses of
the stubs in the import library rather than the addresses of the actual
objects in the DLL. GCC provides the
extension to alleviate this problem a little.
The search algorithm for the runtime library loader is very different to
the algorithms typically used on Unix; I'll explain how to dela with
this in 25.4.5 Runtime Loading of DLLs.
All of the symbols required by a DLL at runtime, must be resolved at
link time. With some creative use of import libraries, it is usually
possible to work around this shortcoming, but it is easy to forget this
limitation if you are developing on a modern system which has lazy
symbol resolution. Be sure to keep it at the back of your mind if you
intend to have your package portable to Windows.
Worst of all, is that it is impossible to reference a non-pointer item
imported from a DLL. In practice, when you think you have exported a
data item from a DLL, you are actually exporting it's address (in fact
the address of the address if you take the import library into
consideration), and it is necessary to add an extra level of indirection
to any non-pointers imported from a DLL to take this into account. The
__declspec extension can handle this automatically
too, at the expense of obfuscating your code a little.
Cygwin support in Libtool is very new, and is being developed very
quickly, so newer versions generally improve vastly over their
predecessors when it comes to Cygwin, so you should get the newest
release you can. The rest of this section is correct with respect to
Libtool version 1.3.5.
In some future version, Libtool might be able to work as transparently
as Autoconf and Automake, but for now designing your packages as
described in this chapter will help Libtool to help us have DLLs
and Unix shared libraries from the same codebase.
The bottom line here is that setting a package up to build and use
modules and libraries as both DLLs and Unix shared libraries
is not straightforward, but the rest of this section provides a recipe
which I have used successfully in several projects, including the module
loader for GNU
m4 1.5 which works correctly with
DLLs on Windows. Lets create hello world as a DLL, and
an executable where the runtime loader loads the DLL.