Prevent name mangling in C (not C++) with MinGW for dynamic symbol search

2.6k views Asked by At

I have a C program where I get function pointers "dynamically" by the function name (ie. I pass the function name as a string and get a pointer to the function). I already do this in Linux using dlopen and dlsym and I suppose it will also work in any other Unix-like with dlfcn.

The problems began when I tried to port this program to Windows using MinGW. When I try to find the name using "GetProcAddress(handle, symbol_name), where "symbol_name" is the name of my callback function and "handle" is a handle to the current executable returned by "GetModuleHandle(NULL)", I get nothing because the MinGW name mangling adds an "_" to my symbol name.

The obvious solution (prefix an "_" to the symbol I want) seems a bit 'dangerous' for portability (may the compiler add two underscores for some of them? I don't know), so, I ask:

  • There is a better way to prevent the compiler from name-mangling my symbols? (or a subset of them, only the callbacks I need to find dynamically);

  • Or a way to make GetProcAddress find them even when mangled?

I also tried the option -fno-leading-underscore, but it removed the mangling of all the external symbols too, making the program impossible to link with the stdlib, etc. (also, the warnings on the documentation are a bit scary).

Also, please note that I'm using pure C -- there is no C++ in any part of my code -- and all my code lives in a single ".exe".

TIA

2

There are 2 answers

2
Pete Kirkham On BEST ANSWER

Not sure what your problem is, as I can't reproduce it with the simplest DLL example I can think of:

/* hello_dll.c */
#include <stdio.h>

__declspec(dllexport) void hello ( void )
{
    puts ( "Hello, DLL!");
}

/* hello_exe.c */
#include <windows.h>
#include <stdio.h>  

int main () {
    typedef void (*pfunc)(void);

    HANDLE hself;

    pfunc hello;

    hself = GetModuleHandle(NULL);

    hello = (pfunc)GetProcAddress(hdll, "hello");

    hello();

    return 0;
}

This is the command line using MinGW gcc with no special flags, and it all works:

gcc src\hello_dll.c src\hello_exe.c -o bin\hello.exe
$ bin\hello.exe
Hello, DLL!
$ gcc --version
gcc (GCC) 4.5.0

It doesn't work without the __declspec(dllexport) if you are getting the function from yourself; when creating a DLL with gcc -shared it doesn't appear to be necessary, but appears to be required if exporting a function from an exe.

0
Codo On

C doesn't use name mangling. In particular, it doesn't add any type information to the name (unlike C++). But some platforms make a small modification to the name like prefixing the underscore. And unlike C++, it's only platform specific but not compiler specific.

On all the platforms I've seen so far, I've only seen either no modification or the leading underscore.

So I propose you use some ifdefs to derive whether the current platform uses an underscore or not.

(Windows has another small modification for certain Windows API functions for distinguishing the ANSI from the Unicode version. But that's probably not relevant for your case.)

Maybe somebody else can point at some official documentation for the C ABI on different platforms.