问题
I'm working in Visual C++, VS2015 Community. I've written this tiny little DLL:
#include "stdafx.h"
int showMsgBox(wchar_t* caption, wchar_t* message)
{
MessageBox(NULL, message, caption, 0);
return 0;
}
And this tiny little client:
#include "stdafx.h"
__declspec(dllimport) int showMsgBox(wchar_t* caption, wchar_t* message);
int main()
{
showMsgBox(L"SimpleDLLClient", L"Hello DLL World!");
return 0;
}
To export the showMsgBox function, I've created this module definition file:
LIBRARY SimpleDLL
EXPORTS
showMsgBox
When I link my client, I pass it the import library that was created when I linked my DLL. Everything compiles and links fine.
And that puzzles me.
According to MSDN, "Because the Visual C++ compiler uses name decoration for C++ functions, you must either use the decorated name as the entryname or internalname, or define the exported functions by using extern "C" in the source code."
But I'm not exporting a decorated name, am I?
If, instead of using a module definition file, I were to prefix the function with the __declspec(dllexport) extended attribute, I wouldn't be surprised (as this ought to have whatever name decoration the compiler applies match the same decoration applied by the compiler to the client).
Likewise, if I prefixed the function with 'extern "C"' in both the DLL and client code, that should also work (and it does: I tested it), because, again, the symbols should match.
But, I would have expected an undecorated export in the module definition file to fail to resolve the client's reference to the same undecorated name, when neither the DLL nor client code uses 'extern "C",' which seems also to be what MSDN says I should expect. Yet, exporting the undecorated name via the module definition file does work, even when I do not use 'extern "C"' anywhere.
Can anyone tell me why this works?
UPDATE
Looking into the files created by the linker, I see that putting the undecorated name into the module definition file apparently results in the decorated name being included in the import library. When I use dumpbin /exports on that file, here's what I get:
File Type: LIBRARY
Exports
ordinal name
?showMsgBox@@YAHPEA_W0@Z (int __cdecl showMsgBox(wchar_t *,wchar_t *))
Now, somewhat amazingly (to me, anyway), if I explicitly alias the decorated name, like this:
LIBRARY SimpleDLL
EXPORTS
showMsgBox=?showMsgBox@@YAHPEA_W0@Z
dumpbin tells me that this is what shows up in the import library:
File Type: LIBRARY
Exports
ordinal name
showMsgBox
Using that as input to the linker when I build the client works fine too, provided that I use 'extern "C"' when I declare my imported function:
extern "C" int showMsgBox(wchar_t* caption, wchar_t* message);
That makes sense, since the symbol the linker is now looking for is the undecorated "showMsgBox," and I have aliased that symbol to the decorated name created when I compiled my DLL.
Soooo...
What it looks like to me is that pages and pages of MSDN documentation that all say you must use decorated names in module definitions files are mistaken. Rather, it appears that if you use the undecorated name in your module definition file, it is the decorated name that is actually incorporated into your import library, which will resolve the reference to the matching decorated name constructed when you compile your client code. That, of course, is what I would prefer, rather than having to extract the decorated names and use those in my module definition files. It just doesn't match what the MSDN pages repeatedly say.
I like to think I'm a bright boy, but it's pretty arrogant of anyone to suggest that Microsoft doesn't know how its own products work.
What am I missing here?
UPDATE 2
With the DLL and client both using decorated names (that is, no use of 'extern "C"' anywhere), everything builds fine with the undecorated name in the module defintion file, like I said. But, interestingly, with no changes at all to the source code, things build equally well if I do use the decorated name in the module definition file:
LIBRARY SimpleDLL
EXPORTS
?showMsgBox@@YAHPEA_W0@Z
At the binary level, the import library this creates is nearly identical to the library created when I use the undecorated name in the module definition file. The only differences appear to be time-stamps, with the exception of one byte near the end. Still trying to make sense of that one, but it appears ever more certain that, somehow, the linker is exporting the decorated name, even when the module definition file refers solely to the undecorated name.
来源:https://stackoverflow.com/questions/36295272/how-do-decorated-names-get-into-import-libraries-when-i-only-provide-the-undecor