If I declare a function like this:
#ifdef TEST_EXPORTS
#define TEST_API __declspec(dllexport)
#else
#define TEST_API __declspec(dllimport)
#endif
TESTAPI int __stdcall myadd(int a, int b);
The symbol in the DLL is _myadd@8
, which makes perfect sense to me (after few hours of reading other questions here, that is).
But the windows libraries seem to do something different. They also use __stdcall
(disguised as WINAPI
), but the symbols in the DLLs have no name decoration. If the method above where in the windows libs, the symbol would be myadd
.
My guess is that they use a def file to alias the symbols. But why does my linker know this when I link to one of these DLLs?
The windows header files declare these functions with WINAPI
, so if I call them, the linker should look for the decorated name, as it is a __stdcall
function. Yet somehow the linker knows to drop the name decoration.
I've tried to replicate this by writing a small DLL and removing the name decoration with a def file. As expected I get linker errors as the linker is still looking for the decorated name. I've done this in pure C, to make sure that c++ name mangling does not effect it.
edit: to clarify, MSVC 14.0 / VS2015, 32-bit
There is some barely documented magic at work here. Lets look some WIN32
API
function, like RegQueryValueExW
. It is defined in the winreg.h
file like this:
WINADVAPI LSTATUS APIENTRY RegQueryValueExW(...);
Where WIADVAPI
is a __declspec(dllimport)
and APIENTRY
is a moniker for the __stdcall
naming convention. Also note, that all functions in the header are declared as extern "C"
. So by all means, this function should use name decoration, and its DLL export should be _RegQueryValueExW@24
. Yet when we are looking advapi32.dll
exports using dumpbin /exports
command, we see an undecorated name:
Now lets closely examine advapi32.lib
file using dumpbin /headers advapi32.lib
command:
Note the undecorate
specifier, that allows to link decorated name to the undecorated export. You could achieve the same result for your dll using a def
file with EXPORTS
section containing undecorated names. See this article and this answer for the additional information.
Also, everything written above is valid only for the x86 applications. C functions in the x64 bit environment are linked without name decoration:
The form of decoration for a C function depends on the calling convention used in its declaration, as shown in the following table. This is also the decoration format that is used when C++ code is declared to have extern "C" linkage. The default calling convention is __cdecl. Note that in a 64-bit environment, functions are not decorated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With