Creating dll in cygwin gives "Undefined reference" errors

Brian Dessent brian@dessent.net
Sat Aug 11 21:28:00 GMT 2007


Pradip Jadav wrote:

> ###create main.exe file.
> g++ -o main.exe main.o -ldl
> 
> ###create .def file
> dlltool.exe --export-all-symbols --output-def main.def main.o
> 
> ###create main library file.
> dlltool.exe --dllname main.exe --def main.def --output-lib libmain.dll.a

This is redundant.  You can achieve all of the above with one step by
creating libmain.dll.a as a side effect of linking main.exe:

g++ -o main.exe main.o -ldl -Wl,-out-implib,libmain.dll.a

> But scene is not this much only.. This was the scene with a single function.
> What if we want to export more than one function from main program?
> What if we want to use a class which is declared in main program(Using
> this class I Want to create a derived class in dll
> 
> code)?
> Do I need to specify "__declspec(dllexport)" for all?
> Is there any other way? Its because my program is quite big. So
> managing code will be very tough na?

In the general sense, yes, you need dllexport on any symbol (function,
class, variable) that you want to make available to another module, and
you need dllimport on the declaration of the symbol in the module that
uses it.

This is typically abstracted away in a single library header file so
that you get a macro that expands to __declspec(dllexport) when building
the library, __declspec(dllimport) when building the user (client) of
the library, and nothing on other platforms like ELF that don't use this
construct (or on PE platforms when building a static version of the
library.)  Then you just use this macro on all external symbols, e.g.

FOO_EXTERN int foo_function (...);

The above is the "ideal" situation, the way the platform was designed to
work.  However, there are several tricks that have been contributed to
the linker that can help in porting code originally designed for non-PE
platforms.  Here again I urge to you read the Win32 section of the
linker manual, as it's all explained there:
<http://sourceware.org/binutils/docs-2.17/ld/WIN32.html>.

The first is auto-exports.  This allows for omitting any explicit
__declspec(dllexport) and instead exporting everything.  Sometimes this
is what you want, but in other cases it results in a huge amount of
useless stuff clogging up the export tables.  In degenerate cases, this
could mean that application startup time is adversely affected.

Worse, it can lead to accidently exporting an internal symbol that is
not supposed to be accessed from outside the module.  This can lead to
all sorts of unexpected and wrong consequences, both in the "program
crash" category and in the "library ABI design headaches" category.  The
linker does provide options for excluding symbols from the auto-export
by regex.

The second half is how to eliminate needing __declspec(dllimport) on
every declaration on the user/client end of the interface.  For function
declarations you may have noticed that you can get away without it --
this is because the import library includes a stub (thunk) with the same
name as the function.  There will be one additional minor level of
indirection in the function call, but no explicit __declspect(dllimport)
is necessary.

However this only works for function calls, not data or classes.  For
those cases there is an ingenious and clever bit of support in the
linker and runtime called pseudo-relocs which can fix this situation. 
The details aren't really all that important because it mostly just
works.  If you see diagnostics such as the following during linking,
it's telling you that those referenced symbols are being resolved using
this technique:

Info: resolving _<sym> by linking to __imp__<sym> (auto-import)

With all of these tricks (auto-exports, import library thunks,
pseudo-relocs) the possibility exists to totally remove the need for any
__declspec in your code.  However, I hope from reading the linker manual
and the above paragraphs that you realize that these are meant as
portability aides, not how the PE platform was designed to work, and
there could possibly be costs to pay for relying on them instead of
being explicit.  In most normal cases I think whatever costs exist would
be minor and likely unmeasurable, but I can certainly come up with
scenarios where they do bite.

Brian

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/



More information about the Cygwin mailing list