mingw32 g++ and stdcall @suffix

10,248

Solution 1

It sounds like you're trying to use MinGW to compile a program that uses external C functions from a third-party dll. There's a way to export those external functions into a proper import library that MinGW's gnu ld linker can use but it involves creating a .def definition file. The advantage with this is once you create a proper import library you won't have to fiddle around with switches like --add-stdcall-alias or --kill-at because the import library will contain the symbols expected by the compiler and linker.

Here's a rough outline of the procedure for doing this:

  1. You'll need a tool call dlltool.exe which should be included in the same MinGW/bin directory as the compiler.
  2. You'll need to create a definition file (*.def) listing all the external functions you're interested in importing.
  3. Create the import file stub (*.a) by running dlltool passing in the .def file you created as input.
  4. Pass the newly created import file *.a to the linker when building your project so the symbols can be resolved properly.

Here's how the definition file looks like:

;Run the dlltool like this:
;dlltool -k -d third_party.def -l libthird_party.a
LIBRARY third_party.dll

EXPORTS
    dll_function1@0
    dll_function2@8
    dll_function3@16
;   ...
    dll_function_n@24

Couple of important things to note. The EXPORTS section has to list the exported symbols/functions in the same name-decorated format as expected by the toolchain. In this case, MinGW compiler and ld linker expects __stdcall C functions to be appended with an '@' follow by the number of bytes in the arguments. The second important thing to note is that dlltool -k will remove the '@', which does the same thing as the --kill-at option you've already seen. The end result of this is you have an import library with the correct internal name-decoration, so things resolve properly, and that internal name will map to the exported visible name found in your 3rd party dll.

One final thing that needs mentioning. Throughout the entire example, we were assuming the undecorated names in the dll used the __stdcall which isn't necessarily true. The following chart(taken from here) shows how different compilers decorate __cdecl vs __stdcall differently:

                  MSVC DLL
Call Convention | (dllexport) | DMC DLL     | MinGW DLL  | BCC DLL
----------------------------------------------------------------------------
__stdcall       | _Function@n | _Function@n | Function@n | Function
__cdecl         | Function    | Function    | Function   | _Function

It's up to you to make sure that the call conventions match-up properly or risk stack corruption and mysterious program crashes.

Solution 2

man ld gives you the --enable-stdcall-fixup option for linking against non-@-decorated libraries. I'm not sure if the leading underscores will be a problem, you'll have to try.

If you want to produce object files or DLLs with mingw and want export names without the "@", --kill-at is your friend.

Share:
10,248
j.l.
Author by

j.l.

Updated on June 16, 2022

Comments

  • j.l.
    j.l. about 2 years

    I declared some C++ functions prototyped as follows:

    extern "C" void __stdcall function();
    

    I also have some third-party dll with exported function() - no name decorations at all. I'm unable to build my exe or dll due to undefined reference to function@..., because of MinGW's stdcall @-suffix. How can I obtain object file without @... just plain function names?

  • j.l.
    j.l. over 12 years
    No, this not work. In addition, if I remember it right, stdcall fixups goes automatically if applicable and one has only to use --disable. What I'm looking for is removing @
  • thiton
    thiton over 12 years
    When you want to link against @'s, that's what stdcall fixups are for. Or do you want to build a DLL with mingw and don't have the symbols exported with @'s?
  • j.l.
    j.l. over 12 years
    As I stated before, I have some third party dll with exported function (and this function probably has to be called via stdcall - because it is used in some old VisualBasic sample) and no decorations at all and I wrote c++ extern function. What I actually need is object file without @-suffix. In this way I can test it twice: 1) execute via c++, 2) test my c++ intermediate in VisualBasic to eliminate some possible pointers-etc.-related issues. But nothing is working, I've tried g++ options, objcopy, ...
  • j.l.
    j.l. over 12 years
    so one possibility is --add-stdcall-alias, this way one can obtain object without (and with) @-suffix. I've already tried it out, but it works only now (maybe linker's options goes last?)