Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

DLL: .def file versus __declspec(dllexport)

1,319 views
Skip to first unread message

Lisa Pearlson

unread,
Feb 24, 2009, 12:22:53 PM2/24/09
to
Hi,

When I create a DLL and I wish to export functions, I can choose between
creating .def file for functions I wish to export, or use
__declspec(dllexport).
What is the difference?

Here are 3 methods tried and under which name they were exported:

.def :
MyFunc

.def with extern "C"
MyFunc

__declspec(dllexport)
?MyFunc@YGHPB...

__declspec(dllexport) with extern "C"
_MyFunc@16

I understand why there is name mangling for C++ (allow export of overloaded
functions and such, right?)
But not the difference between .def and __declspec(dllexport)
.. or more particularly, why the latter does not give same result as extern
"C", but "_ ... @N" format instead?

Lisa


Codeplug

unread,
Feb 24, 2009, 12:43:37 PM2/24/09
to
Lisa Pearlson wrote:
>
> __declspec(dllexport) with extern "C"
> _MyFunc@16
>
This is __stdcall. Are you sure you didn't have a "WINAPI" or "CALLBACK"
in the declaration of MyFunc?

By default, MSVC uses __cdecl for C and C++.
http://msdn.microsoft.com/en-us/library/984x0h58.aspx

gg

Giovanni Dicanio

unread,
Feb 24, 2009, 1:27:55 PM2/24/09
to

"Codeplug" <Code...@nospam.invalid> ha scritto nel messaggio
news:dlWol.16295$FI5....@newsfe07.iad...

> Lisa Pearlson wrote:
>>
>> __declspec(dllexport) with extern "C"
>> _MyFunc@16
>>
> This is __stdcall. Are you sure you didn't have a "WINAPI" or "CALLBACK"
> in the declaration of MyFunc?

In addition, if you want both __stdcall calling convention and no
declaration (e.g. just 'MyFunc' with __stdcall and extern "C"), the only
option you have is to use .def files.

For all other cases, I would suggest using __declspec.

Giovanni


Lisa Pearlson

unread,
Feb 25, 2009, 9:36:40 AM2/25/09
to
WINAPI and CALLBACK is defined as __stdcall, so should be identical, right?

I still don't understand why extern "C" with __declspec(dllexport) exports
function as "_ Func @ N" instead of just "Func" that I get when exporting
with .def file.

Lisa

"Codeplug" <Code...@nospam.invalid> wrote in message
news:dlWol.16295$FI5....@newsfe07.iad...

Alex Blekhman

unread,
Feb 25, 2009, 9:58:46 AM2/25/09
to
"Lisa Pearlson" wrote:
> I still don't understand why extern "C" with
> __declspec(dllexport) exports function as "_ Func @ N" instead
> of just "Func" that I get when exporting with .def file.

Historically .DEF files precede __declspec(dllexport) specifier. A
function which is exported via .DEF file will be stripped of any
name decoration (be it C or C++ decoration). Long time ago .DEF
files were the only way to export functions and data. People used
to write the same name of a fuction in a .DEF file as it appeared
in C code regardless of calling convention.

When __declspec(dllexport) specifier emerged, then each calling
convention got its own name decoration scheme. Both C and C++
functions get decorated when exported. The difference is that
there is an agreement between compiler vendors about C decoration
scheemes, while C++ decoration is specific to each vendor, thus
incompatible between different compilers.

Alex


Lisa Pearlson

unread,
Feb 25, 2009, 10:15:46 AM2/25/09
to
Thank you for wonderful explanation.
So this confirms .def is not identical to export "C" with
__declspec(dllexport).

So for compatibility, it's recommended to use .def?
Is there any advantage to using __declspec(dllexport) with extern "C" ?

Lisa

"Alex Blekhman" <tkfx....@yahoo.com> wrote in message
news:O29mQm1l...@TK2MSFTNGP06.phx.gbl...

Ulrich Eckhardt

unread,
Feb 25, 2009, 10:25:25 AM2/25/09
to
Lisa Pearlson wrote:
> Is there any advantage to using __declspec(dllexport) with extern "C" ?

The calling convention is coded into the exported symbol, so mismatches will
be caught at link time.

Uli

--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932

Codeplug

unread,
Feb 25, 2009, 11:01:52 AM2/25/09
to
Lisa Pearlson wrote:
> WINAPI and CALLBACK is defined as __stdcall, so should be identical, right?
Yes, WINAP and CALLBACK are usually both defined as __stdcall.

> I still don't understand why extern "C" with __declspec(dllexport) exports
> function as "_ Func @ N" instead of just "Func" that I get when exporting
> with .def file.

Keep in mind that both the "linkage" and the "calling convention" can
affect the "decoration" of a symbol:

extern "C" __stdcall will give you "_Func@N"
extern "C" __cdecl will give you "Func", just like .def

> Thank you for wonderful explanation.
> So this confirms .def is not identical to export "C" with
> __declspec(dllexport).

It is when it's __cdecl.

> So for compatibility, it's recommended to use .def?

"Compatibility" depends on the who the clients of the DLL are and what
they expect.

> Is there any advantage to using __declspec(dllexport) with extern "C" ?

The advantage is not having to write and maintain a .def file :)

gg

Ben Voigt [C++ MVP]

unread,
Feb 25, 2009, 1:12:11 PM2/25/09
to
Codeplug wrote:
> Lisa Pearlson wrote:
>> WINAPI and CALLBACK is defined as __stdcall, so should be identical,
>> right?
> Yes, WINAP and CALLBACK are usually both defined as __stdcall.
>
>> I still don't understand why extern "C" with __declspec(dllexport)
>> exports function as "_ Func @ N" instead of just "Func" that I get
>> when exporting with .def file.
> Keep in mind that both the "linkage" and the "calling convention" can
> affect the "decoration" of a symbol:
>
> extern "C" __stdcall will give you "_Func@N"
> extern "C" __cdecl will give you "Func", just like .def

no, it will give you "_Func". The only way to prevent any decoration is
with the .def file.


Codeplug

unread,
Feb 25, 2009, 1:20:34 PM2/25/09
to
No - try it yourself...Or read the [latest] documentation...
http://msdn.microsoft.com/en-us/library/zkwh89ks.aspx

gg

Ben Voigt [C++ MVP]

unread,
Feb 25, 2009, 1:53:29 PM2/25/09
to
>>> extern "C" __cdecl will give you "Func", just like .def
>>
>> no, it will give you "_Func". The only way to prevent any
>> decoration is with the .def file.
>>
> No - try it yourself...Or read the [latest] documentation...
> http://msdn.microsoft.com/en-us/library/zkwh89ks.aspx

Just tested it myself (again) with Visual Studio 2005 SP1.

extern "C" __declspec(dllexport) int __cdecl Test( double ) { return 0; }

turns into (ran dumpbin on the generated import library):

File Type: LIBRARY

Exports

ordinal name

_Test

and dumpbin on the DLL itself:

ordinal hint RVA name

4 0 00001160 Test = _Test


The underscore is clearly present.

I'd advise showing an actual example, not referencing documentation that
doesn't even address the question at hand, when contradicting an MVP.
Otherwise you just end up making yourself look bad when it turns out they
were right after all.


Cholo Lennon

unread,
Feb 25, 2009, 3:30:24 PM2/25/09
to
Ben Voigt [C++ MVP] wrote:
>>>> extern "C" __cdecl will give you "Func", just like .def
>>>
>>> no, it will give you "_Func". The only way to prevent any
>>> decoration is with the .def file.
>>>
>> No - try it yourself...Or read the [latest] documentation...
>> http://msdn.microsoft.com/en-us/library/zkwh89ks.aspx
>
> Just tested it myself (again) with Visual Studio 2005 SP1.
>
> extern "C" __declspec(dllexport) int __cdecl Test( double ) { return
> 0; }
>
> turns into (ran dumpbin on the generated import library):
>
> File Type: LIBRARY
>
> Exports
>
> ordinal name
>
> _Test
>
> and dumpbin on the DLL itself:
>
> ordinal hint RVA name
>
> 4 0 00001160 Test = _Test
>
>
> The underscore is clearly present.
>
> I'd advise showing an actual example, not referencing documentation
> that doesn't even address the question at hand, when contradicting an
> MVP.

I understand your point (in this case), but be careful, MVPs not always are
right...

> Otherwise you just end up making yourself look bad when it turns
> out they were right after all.

--
Cholo Lennon
Bs.As.
ARG

Codeplug

unread,
Feb 25, 2009, 3:56:35 PM2/25/09
to
Ben Voigt [C++ MVP] wrote:
> Just tested it myself (again) with Visual Studio 2005 SP1.
>
> extern "C" __declspec(dllexport) int __cdecl Test( double ) { return 0; }
>
> turns into (ran dumpbin on the generated import library):
>

There's no point at looking at the import library to see what a DLL
exports - when you can just look at the DLL.

> and dumpbin on the DLL itself:
>
> ordinal hint RVA name
>
> 4 0 00001160 Test = _Test
>
>
> The underscore is clearly present.

"Test" is also clearly present (and listed first). Use depends.exe if
you like. You will see "Test" as the exported symbol name. Use
GetProcAddress() if you like, you will need to pass in "Test".

> I'd advise showing an actual example, not referencing documentation that
> doesn't even address the question at hand, when contradicting an MVP.

[Quote:]
[__cdecl] name-decoration convention -
Underscore character (_) is prefixed to names, *except when exporting
__cdecl functions that use C linkage*.
[End Quote]

Doesn't that address our disagreement directly?

> Otherwise you just end up making yourself look bad when it turns out they
> were right after all.

Indeed!

BTW, I'd love to know the results of your dumpbin test when using a .def
file for Test().

gg

Codeplug

unread,
Feb 25, 2009, 4:12:00 PM2/25/09
to
Codeplug wrote:
> BTW, I'd love to know the results of your dumpbin test when using a .def
> file for Test().

That was a bit petty of me. The point was that you get the same results
either way.

Back to the original disagreement:

> no, it will give you "_Func". The only way to prevent any decoration is
> with the .def file.

By comparing the dumpbin results between using .def and using extern "C"
__cdecl - you will see no differences. Therefore, either method works
equally well to achieve the same result.

gg

Ben Voigt [C++ MVP]

unread,
Feb 26, 2009, 9:53:11 AM2/26/09
to
> [Quote:]
> [__cdecl] name-decoration convention -
> Underscore character (_) is prefixed to names, *except when exporting
> __cdecl functions that use C linkage*.
> [End Quote]
>
> Doesn't that address our disagreement directly?

Well no, this refers to functions exported from the compile unit (i.e.
non-static linkage, not in the anonymous namespace). It most definitely
affects linking together .obj files and .lib files when no DLLs are in use
whatsoever.

__declspec(dllexport) is a different beast not directly addressed by the
documentation you cited.

Moreover, the documentation appears to be wrong. The generated object files
(and error messages concerning undefined externals) do have an underscore
(speaking from experience, not a new bout of testing).


Codeplug

unread,
Feb 26, 2009, 11:53:08 AM2/26/09
to
Ben Voigt [C++ MVP] wrote:
>> [Quote:]
>> [__cdecl] name-decoration convention -
>> Underscore character (_) is prefixed to names, *except when exporting
>> __cdecl functions that use C linkage*.
>> [End Quote]
>>
>> Doesn't that address our disagreement directly?
>
> Well no, this refers to functions exported from the compile unit (i.e.
> non-static linkage, not in the anonymous namespace).

[snip]
The use of the term "exporting" in the quoted documentation obviously
does not refer to _external_ symbols in a compilation unit...the dumpbin
tests verified that much. Of course, external symbol names in object
file have little or nothing to do with this thread...

> __declspec(dllexport) is a different beast not directly addressed by the
> documentation you cited.
>
> Moreover, the documentation appears to be wrong. The generated object files
> (and error messages concerning undefined externals) do have an underscore
> (speaking from experience, not a new bout of testing).

The docs are correct, despite incorrect interpretations. One could
suggest a clarification such as: "except when exporting from Dll's" -
but that seems redundant to me - what else would you be "exporting" from?

gg

Doug Harrison [MVP]

unread,
Feb 26, 2009, 12:44:58 PM2/26/09
to
On Thu, 26 Feb 2009 11:53:08 -0500, Codeplug <Cod...@nospam.invalid>
wrote:

>The docs are correct, despite incorrect interpretations. One could
>suggest a clarification such as: "except when exporting from Dll's" -
>but that seems redundant to me - what else would you be "exporting" from?

It's unusual, but EXEs can export functions, and DLLs loaded into their
processes can GetProcAddress them. The kernel EXEs export a bunch of
functions, e.g. try:

dumpbin /exports ntkrnlpa.exe

--
Doug Harrison
Visual C++ MVP

Ben Voigt [C++ MVP]

unread,
Feb 26, 2009, 7:10:54 PM2/26/09
to
> The docs are correct, despite incorrect interpretations. One could
> suggest a clarification such as: "except when exporting from Dll's" -
> but that seems redundant to me - what else would you be "exporting"
> from?

"export" is a C++ keyword, didn'tcha know. And it has absolutely nothing to
do with DLLs. Of course, that's not how Microsoft is using the word here,
but still.

>
> gg


Tim Roberts

unread,
Feb 28, 2009, 10:59:26 PM2/28/09
to
"Lisa Pearlson" <n...@spam.plz> wrote:

>Thank you for wonderful explanation.
>So this confirms .def is not identical to export "C" with
>__declspec(dllexport).
>
>So for compatibility, it's recommended to use .def?
>Is there any advantage to using __declspec(dllexport) with extern "C" ?

There's another way to do this without using a .def file. You can say:

#pragma comment( linker, "/export:_MyFunc" )

extern "C"
void MyFunc( ... )

I like this, because it keeps all the knowledge about the function in one
spot.
--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

0 new messages