Valhalla Legends Forums Archive | C/C++ Programming | DLL Function Name "Decoration"

AuthorMessageTime
NicoQwertyu
I'm trying to build a DLL in gcc, but the function names always end up getting mangled.

I'm not sure if I'm doing something wrong, or if it's some wierd compiler issue (GCC and MinGW).

[code]
extern "C" __declspec(dllexport) LRESULT CALLBACK msgproc(int nCode, WPARAM wParam, LPARAM lParam);
[/code]


[code]
__declspec(dllexport) LRESULT CALLBACK msgproc(int nCode, WPARAM wParam, LPARAM lParam) {

...

}
[/code]


Compiled with:
[code]
gcc plugin_message.cpp -shared -o ../build/plugin_message.dll
[/code]


The DLL compiles fine, but when I check the exports, the function name is still mangled.  Any one more experienced with this compiler know what the problem is?
June 5, 2005, 6:26 PM
OnlyMeat
You can specify specific export function names on the command line for the linker. However an easier way is to use a .def file in which the contents specify the exported names. For example:-

-- MyLib.def --
[code]
LIBRARY      "MyLib"
DESCRIPTION  "My exported library"

EXPORTS
  Function1 @1
[/code]

Then add a /DEF: MyLib.def on the linker command line.

Generally name mangling shouldn't be a problem, unless you are calling from vb.
June 5, 2005, 8:18 PM
Kp
I usually don't mix C++ and DLLs, but I've never had the problem you're experiencing.  Did you actually put both those code blocks in one file?  Also, it's traditional to name C++ files with .cc not .cpp.  Among other advantages, it prevents MSVC++ from recognizing them.  If those two code blocks are in one file, I can raise a Windows box and check my build process for you.  I do some strange constructs to minimize the number of exported symbols and extra libraries drawn in, so I'd need to check my notes.
June 5, 2005, 8:21 PM
NicoQwertyu
OnlyMeat: I forgot to mention that I also tried using a .def file. 

[quote]gcc plugin_message.cpp -shared -o ../build/plugin_message.dll plugin_message.def
Warning: resolving _msgproc by linking to _msgproc@12[/quote]

While the DLL compiles, it renders some strange exports, and still doesn't export the function the way I want it to.



KP: Yeah, they're both in one file.

[quote]I usually don't mix C++ and DLLs[/quote]

What for?  I'm still new to C++, so I'm open to any suggestions.  Even when I change the file extension to .c, and fix all the new errors generated by gcc, it still mangles the function name.

June 5, 2005, 8:34 PM
R.a.B.B.i.T
gcc -c -DBUILD_DLL sourcefile
dllwrap --output-lib=liboutputfile.a --dllname=name.dll --driver-name=gcc objectfile

Don't forget to wrap!
June 5, 2005, 9:29 PM
NicoQwertyu
[quote author=rabbit link=topic=11773.msg114970#msg114970 date=1118006944]
gcc -c -DBUILD_DLL sourcefile
dllwrap --output-lib=liboutputfile.a --dllname=name.dll --driver-name=gcc objectfile

Don't forget to wrap!
[/quote]

That yeilds even stranger results.
June 5, 2005, 10:03 PM
Kp
[quote author=NicoQwertyu link=topic=11773.msg114966#msg114966 date=1118003696][quote]gcc plugin_message.cpp -shared -o ../build/plugin_message.dll plugin_message.def
Warning: resolving _msgproc by linking to _msgproc@12[/quote][/quote]

This is a serious warning!  In my opinion, it ought to be a full-blown error, actually.  It means you declared a function as _cdecl in one place, and as _stdcall in another, so calling it will corrupt your stack pointer.  This must be fixed before you can safely call msgproc.

[quote author=NicoQwertyu link=topic=11773.msg114966#msg114966 date=1118003696][quote]I usually don't mix C++ and DLLs[/quote]What for?[/quote]
The projects for which I want DLLs are generally low level and/or mix in some assembly, so C++ name mangling just gets to be a horrible nuisance.  There's no technical reason why you should or shouldn't prefer C over C++ for DLLs.

[quote author=NicoQwertyu link=topic=11773.msg114966#msg114966 date=1118003696]I'm still new to C++, so I'm open to any suggestions.  Even when I change the file extension to .c, and fix all the new errors generated by gcc, it still mangles the function name.[/quote]

That behavior definitely should not happen.  If gcc is compiling it as C code, it should not be mangling the name.  Just so I can be sure I try exactly your problem, run this in a command prompt and paste all the output back:

[pre]type plugin_message.cpp
gcc plugin_message.cpp -shared -o ../build/plugin_message.dll plugin_message.def[/pre]

If you want to keep your message contents private, strip out the body of the function; all I really need are the lines at global scope.  Also, as one other thing to try: build to a .o file, then link the .o file and .def to make a DLL..  To do that:

[pre]gcc -c plugin_message.cpp
gcc plugin_message.o plugin_message.def -shared -o output.dll[/pre]This is from memory, but should work.  My build process is driven by interlocking makefiles and invokes ld directly, so that I can skip the cruft that the MinGW project normally drags in.
June 5, 2005, 10:43 PM
NicoQwertyu
First:

[quote]
Kyle@NA-0060YM1FOOF2 ~/src/plugin_notepad/plugindll
$ type plugin_message.cpp
plugin_message.cpp is ./plugin_message.cpp

Kyle@NA-0060YM1FOOF2 ~/src/plugin_notepad/plugindll
$ gcc plugin_message.cpp -shared -o ../build/plugin_message.dll plugin_message.
def
Warning: resolving _msgproc by linking to _msgproc@12
Use --enable-stdcall-fixup to disable these warnings
Use --disable-stdcall-fixup to disable these fixups

Kyle@NA-0060YM1FOOF2 ~/src/plugin_notepad/plugindll
$
[/quote]

Second:
Same output as first.


plugin_message.cpp -- function contents stripped out, not because I want to keep them private, but to save room.

[quote]
#include <windows.h>
#include <string.h>


#define EXPORT __declspec(dllexport)
#define MSG_DOSTUFF 33001


void strippath(char *s);
void dostuff();
extern "C" __declspec(dllexport) LRESULT CALLBACK msgproc(int nCode, WPARAM wParam, LPARAM lParam);




bool in_target = false;


extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {

}



extern "C" __declspec(dllexport) LRESULT CALLBACK msgproc(int nCode, WPARAM wParam, LPARAM lParam) {

}


void dostuff() {

}


void strippath(char *s) {

}
[/quote]


plugin_message.def

[quote]
LIBRARY "plugin_message.dll"
DESCRIPTION "mmmm"
EXPORTS
msgproc @1
[/quote]


Makefile:

[quote]
all: plugin_message.cpp
gcc plugin_message.cpp plugin_message.def -shared -o ../build/plugin_message.dll

[/quote]
June 5, 2005, 11:05 PM
Kp
OK, I wasn't expecting a custom shell.  The msgproc warning is actually because you're trying to export it unnamed, which isn't nearly as bad as I initially thought.  You can make that go away by changing your .DEF file to read:[pre]LIBRARY "plugin_message.dll"
DESCRIPTION "mmmm"
EXPORTS
  msgproc@12=msgproc @1[/pre]My Makefile comment was just explanation of why I didn't have the full link procedure on hand: because I do things in very complicated and bizarre ways. :)  I'll try out your code on my Windows box when I get to it and edit in my results.
June 6, 2005, 12:38 AM
NicoQwertyu
Thanks for your replys, kp.  A quick comment before I go watch Starwars III.  Is that export correct?  When I switch it around (msgproc=msgproc@12 @1) is resolves the warning, and leaves the DLL with two exports (one of them being msgproc).  Ran into a new problem, however; GetProcAddress fails, but I'm sure that's my own fault.  I'll check back in a few hours.  Thanks again for your help.
June 6, 2005, 1:35 AM
R.a.B.B.i.T
HAH!  I just realized.  Use g++ for compiling c++ files.
June 6, 2005, 3:09 AM
NicoQwertyu
[quote author=rabbit link=topic=11773.msg115013#msg115013 date=1118027346]
HAH!  I just realized.  Use g++ for compiling c++ files.
[/quote]

I tried that before I posted this also.  gcc is fully capable of compiling c++ files.
June 6, 2005, 3:41 AM
NicoQwertyu
[quote]Ran into a new problem, however; GetProcAddress fails, but I'm sure that's my own fault.[/quote]

It was my fault :P!  Everything is working now. Thanks for all the replies.

[size=1]FARPROC hfunc = GetProcAddress(hdll, "msgproc");[/size]

Apparently, is very different from:

[size=1]FARPROC hfunc = GetProcAddress(hdll, (LPCSTR)"msgproc");[/size]
June 6, 2005, 6:11 AM
Kp
It shouldn't be.  I never cast strings that I pass to GetProcAddress.  Post a disassembly of both forms here, please. :)

objdump -d objfile.o
June 6, 2005, 11:31 PM
NicoQwertyu
Nevermind.  I guess it doesn't make a difference.  There must have been a different problem a while back when it wouldn't work.
June 7, 2005, 12:54 AM

Search