locked
Creating a .DLL -- what does __declspec(dllexport) get me? RRS feed

  • Question

  • I've only created a handful of .DLL's in my life and the last time I did it was several years ago.  After reading through the MSDN documentation for VS2008, I came across __declspec(dllexport).  If I define the following function:

    extern "C" __declspec(dllexport) int  __cdecl Add( int a, int b)
    {
      return a + b;
    }

    and compile the project as a DLL, I see that a .dll file is created and when I view it with dumpbin /exports, the function name has not been mangled/decorated (this is what I was intending by adding extern "C").  From this experiment I hypothesize that extern "C" is working as desired and __declspec(dllexport) told the linker i wanted the function to be public -- it also seemed to create a .lib file in case I don't want to use LoadLibrary.  However, I don't care about the .lib file as I can only use LoadLibrary for my application.

    So if I make one minor change to the function above -- change __cdecl to __stdcall, you will notice that everything still compiles, but now when I check dumpbin, it shows the name has been decorated to something like _Add@8 (underscore preceding the function name, @[size of arguments]).  This is not what I want.  The only way I have found to get around this is to do it the way I did it 8+ years ago -- using a .DEF file.  Now, DEF files are not exactly rocket science so it was trivial to get it working, but I just cannot understand why this would work for one calling convention and not the other?  Yes, I know stdcall and cdecl differ in whether the caller or callee are responsible for cleaning the stack and that is why the size of the params must be specified, but why can't __declspec(dllexport) just do the same thing the DEF file does so I don't have to create a DEF file?

    I must be missing something here.

    I haven't tried yet, but I suspect the __cdecl attempt will fail if  I try to overload the function.  In my eyes, DEF is the only reliable way to do what I want to do....but why have __declspec(dllexport) at all then?

    Your insight is appreciated.

    Thanks,
    Adam
    Monday, December 21, 2009 7:35 PM

Answers

  • There are two different types of name mangling coming into play. One is C++ name mangling, the other is calling convention name mangling. Using extern "C" is removing the C++ name mangling, but the leading underscore and trailing @number is part of the calling convention name mangling. Using a .def file to export a function with non-cdecl calling convention in effect renames the export. It would be nice if dllexport took a parameter to rename the symbol as well, to remove the need for a .def file; maybe a good candidate for a feature request on MS Connect?
    • Marked as answer by AdamForum Tuesday, December 22, 2009 3:49 AM
    Tuesday, December 22, 2009 1:50 AM

All replies

  • That is the calling convention for __stdcall.
    «_Superman_»
    Microsoft MVP (Visual C++)
    Monday, December 21, 2009 7:58 PM
  • That is the calling convention for __stdcall.
    «_Superman_»
    Microsoft MVP (Visual C++)

    Yes, I am familiar with many calling conventions, including __stdcall, but I don't understand why it is mangling/decorating the name even when I have specified the function to be extern "C" ?

    If I create a .DEF file, the DLL is created properly (e.g. I can call LoadLibrary using the name of my function, without needing to specify decorations or argument sizes). 

    Why isn't the linker smart enough to realize I'm using extern "C" with __stdcall and just take care of the mapping on its own?  The .DEF file seems like an unnecessary layer to maintain.

    Tuesday, December 22, 2009 1:11 AM
  • The __stdcall calling convention specifically mentions that it performs name mangling following this behavior:

    "An underscore (_) is prefixed to the name. The name is followed by the at sign (@) followed by the number of bytes (in decimal) in the argument list. Therefore, the function declared as int func( int a, double b ) is decorated as follows: _func@12"

    That is part of the __stdcall convention itself.  Removing that would violate the "standard" __stdcall convention.  If you want to use __stdcall, but not use the standard conventions for it, you need to use a DEF file to remap the names.
    Reed Copsey, Jr. - http://reedcopsey.com
    Tuesday, December 22, 2009 1:41 AM
  • There are two different types of name mangling coming into play. One is C++ name mangling, the other is calling convention name mangling. Using extern "C" is removing the C++ name mangling, but the leading underscore and trailing @number is part of the calling convention name mangling. Using a .def file to export a function with non-cdecl calling convention in effect renames the export. It would be nice if dllexport took a parameter to rename the symbol as well, to remove the need for a .def file; maybe a good candidate for a feature request on MS Connect?
    • Marked as answer by AdamForum Tuesday, December 22, 2009 3:49 AM
    Tuesday, December 22, 2009 1:50 AM
  • There are two different types of name mangling coming into play. One is C++ name mangling, the other is calling convention name mangling. Using extern "C" is removing the C++ name mangling, but the leading underscore and trailing @number is part of the calling convention name mangling. Using a .def file to export a function with non-cdecl calling convention in effect renames the export. It would be nice if dllexport took a parameter to rename the symbol as well, to remove the need for a .def file; maybe a good candidate for a feature request on MS Connect ?
    Thanks for the explanation.  I did notice the name seemed less mangled when I added extern "C" (as opposed to just having __stdcall), but I read so much documentation on the site saying you either had to use __declspec(dllexport) OR make a .DEF file, I was thinking there was another solution to get it to work without needing a .DEF.  I don't really care enough to make a request to MS Connect -- they have more important issues to fix.  Thanks again for the feedback.

    Adam
    Tuesday, December 22, 2009 3:54 AM