[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

DLL_EXPORT and MinGW/Cygwin

From: Jon Leichter
Subject: DLL_EXPORT and MinGW/Cygwin
Date: Thu, 20 Dec 2001 20:53:49 -0800

Hello all.

It's been a long time since I've posted to this mailing list. In the past, I
made some contributions to libtool, where it concerned Cygwin and MinGW.

I haven't used these environments for a while, but I am using them once
again. I see that the support for these targets has been updated quite a
bit. However, I now see some new issues that I'd like to discuss. I'm going
to focus on only one issue in this email, since it's very detailed. I'll
post another email about another issue.

I tried to make a pass at searching the mailing list archives, but there
does not seem to be a sophisticated search mechanism, so I didn't find much.

The issue: DLL_EXPORT. It appears that this macro is defined by 'libtool' as
a PIC flag for Cygwin and/or MinGW. It seems that the intent of this macro
is to aid developers who are building shared objects. A developer can use
this macro in the preprocessing of his header files. It's to be an indicator
that the header is being included in a source file that is getting compiled
as a shared object that will be part of the DLL. This scheme is flawed for a
few different reasons.

First of all, the intent of DLL_EXPORT is to enable the developer to use the
__declspec(dllexport) directive. For libtool, this directive is superfluous.
This is because libtool goes through the trouble of generating an .exp file,
which is fed to the linker. The final DLL will have the correct exports with
or without this directive being declared.

Secondly, even if someone could convince me that using __declspec(dllexport)
was necessary, the DLL_EXPORT macro is too generic. DLL_EXPORT preprocessed
in a header for the library being built might be fine, but when a header
outside of the library is being included, this can cause problems. Consider
an example. Say I am building a shared library called libexample.dll, whose
one and only object file is example.o.

Suppose this was example.h:

         * I'm not going to bother with __declspec(dllimport)
         * since it's irrelevant to the example
        #ifdef DLL_EXPORT
        #       define EXTERN extern __declspec(dllexport)
        #       define EXTERN extern

        EXTERN int myfunc(void);

Suppose this was example.c:

        #include "ltdl.h"
        #include "example.h"

        int myfunc(void)
                lt_dlmalloc = 0; /* just for fun */
                return 0;

Now, if I use libtool to compile this file (using say MinGW gcc):

        $ libtool --mode=compile gcc -I/usr/local/include -c example.c
        rm -f .libs/example.lo
        gcc -I/usr/local/mingw/include -c example.c  -DDLL_EXPORT -DPIC -o
        gcc -I/usr/local/mingw/include -c example.c -o example.o >/dev/null 2>&1
        mv -f .libs/example.lo example.lo

I believe that I have used DLL_EXPORT in a manner that is intended. In this
manner, it indicates to the compiler that myfunc() is being exported. But
here's the GOTCHA: Because I have included ltdl.h, it ALSO indicates that
lt_dlmalloc is being exported from the resulting object file. This is
because ltdl.h uses DLL_EXPORT for various symbols (like the variable
lt_dlmalloc) exactly the same way that I that used it for myfunc(). Since
lt_dlmalloc is not ever defined in my source file, the compiler never
actually exports it. However, it was a flaw for it to believe that it ever
would export it.

In fact, if I KNOW that I'm going to link my library with the dynamic
version of libltdl, then I should REALLY be defining LIBLTDL_DLL_IMPORT in
my compilation line. If I don't do this, I will not really end up setting a
value for lt_dlmalloc. The problem, however, is that ltdl.h I get a warning
about LT_SCOPE to being redefined:

        $ libtool --mode=compile
gcc -DLIBLTDL_DLL_IMPORT -I/usr/local/mingw/include -c example.c
        rm -f .libs/example.lo
        gcc -DLIBLTDL_DLL_IMPORT -I/usr/local/mingw/include -c
xample.c  -DDLL_EXPORT -DPIC -o .libs/example.lo
        In file included from example.c:1:
        /usr/local/mingw/include/ltdl.h:134: warning: `LT_SCOPE' redefined
        /usr/local/mingw/include/ltdl.h:131: warning: this is the location of 
previous definition
        gcc -DLIBLTDL_DLL_IMPORT -I/usr/local/mingw/include -c example.c -o
example.o >/dev/null 2>&1
        mv -f .libs/example.lo example.lo

Part of the problem here is the way that ltdl.h handles the order of
preprocessing LIBLTDL_DLL_IMPORT and DLL_EXPORT. However, the bigger problem
is the fact that DLL_EXPORT cannot act as a generic "export" macro for
header files. It's fine for headers that are part of the library, but not
for headers of other libraries that will be imported.

DLL_EXPORT can and should be eliminated altogether. It should absolutely be
taken out of libtool.m4 as the PIC flag for Cygwin and MinGW. If someone is
going to insist that it remain when libltdl gets built, then the macro
should at least be changed to LIBLTDL_DLL_EXPORT in ltdl.h.

It's really up to the developer to figure out how to make his header file
intelligent about using __declspec directives. In libraries that I have
developed, I never use __declspec(dllexport). As for importing, I define
EXTERN to __declspec(dllimport) by default UNLESS a macro whose name matches
the library's name is defined. For me, this model has worked without a


reply via email to

[Prev in Thread] Current Thread [Next in Thread]