The dllexport attribute tells the linker to generate an export table entry for the specified function. This export entry is decorated. This is necessary to support
dllexporting of overloaded functions. But it also means that the string you pass to
GetProcAddress needs to be decorated.
As we learned earlier, the decoration scheme varies from architecture to architecture and from calling convention to calling convention. So, for example, if the function is exported from a PPC DLL, you would have to do
GetProcAddress(hinst, "..SomeFunction"), but if it is exported from an 80386 DLL as extern “C” __stdcall, you would need
GetProcAddress(hinst, "_SomeFunction@8"), but if it’s __fastcall you would need
What’s more, C++ decoration varies from compiler vendor to compiler vendor. A C++ exported function might require
GetProcAddress(hinst, "?SomeFunction@@YGXHH@Z") if compiled with the Microsoft C++ compiler, but some other decorated string if compiled with the Borland C++ compiler.
So if you intend people to be able to
GetProcAddress for functions and you intend your code to be portable to multiple platforms, or if you intend them to be able to use your DLL from a language other than C/C++ or use a C++ compiler different from Microsoft Visual Studio, then you must export the function by its undecorated name.
When a DLL is generated, the linker produces a matching LIB file which translates the decorated names to undecorated names. So, for example, the LIB file has an entry that says, “If somebody asks for the function _GetTickCount@0, send them to kernel32!GetTickCount.”
dllexport ties you to an architecture, compiler, and language (by exporting decorated names), then why does MSVCRT.DLL use it?