CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Dec 2004
    Location
    Poland
    Posts
    1,165

    [Solved] GCC, dynamic linking and calling conventions

    Hello

    I am trying to develop Windows application using DevCpp and GCC compiler v.3.2.4. Application uses mylib.dll library compiled with MSVC 7 and this causes the incompatibility problems. Some functions (almost all) at mylib.dll use __stdcall calling convention, while GCC compiler uses __cdecl by default. This behaviour can be changed globally using -mrtd switch.
    Because of problems with linking MSVC dlls to GCC apps, I decided to link mylib.dll dynamically. Using LoadLibrary and GetProc Address I assign address of proc to function pointer, and call it in my program:

    Code:
    typedef void (*myfunc)(void); //function pointer declaration
    ....
    //this one works
    LoadLibrary("mylib.dll");
    //this one too
    myfunc func1 = (myfunc)GetProcAddress("_func1@0");//strange name, since itd __stdcall one and is not aliased
    .......
    //some lines later.....
    just_a_func(); // <-- function defined in program or other GCC library, __cdecl call by default
    func1(); //<--__stdcall imported func
    Now whats the question: Is there any way to force GCC compiler to call some functions pointed by pointers using __stdcall, and some others pointed by pointers and defined in program using __cdecl?

    I was trying following things:
    1. use -mrtd switch: works OK but only as long as my app calls ONLY __stdcall procs. When this option is used, app cannot correctly call functions from other GCC libs, as they use __cdecl.

    2. do not use -mrtd switch, and declare function pointer as using __stdcall
    Code:
    typedef void (*__stdcall myfunc)(void); //doesnt work, function is still called as __cdecl
    typedef void (*myfunc)(void) __attribute__((stdcall)); //same as above
    Either its not possible to specify calling convention of function pointer, or I am doing something wrong, or GCC ignores calling specifiers in C++ modules.

    I found a lot of examples 'How to link GCC app with MSVC dll', and I tried them. Indeed, linker does not complain, but this does not prevent GPFs and stack troubles at runtime.

    Thanks for help
    Hob
    Last edited by Hobson; June 7th, 2005 at 04:48 AM.
    B+!
    'There is no cat' - A. Einstein

    Use &#91;code] [/code] tags!

    Did YOU share your photo with us at CG Members photo gallery ?

  2. #2
    Join Date
    Feb 2005
    Location
    Normandy in France
    Posts
    4,590

    Re: GCC, dynamic linking and calling conventions

    It is possible to use _stdcall for some functions and _cdecl for others, there is no problem, even with static linking to DLL.

    But you must be careful with the position of the _stdcall specifier:
    Quote Originally Posted by Hobson
    Code:
    typedef void (*__stdcall myfunc)(void); //doesnt work, function is still called as __cdecl
    It defines a _stdcall pointer to a _cdecl function (what means that if you declare a global variable with this type, the global variable name will be mangled without underscore character), and not a pointer to a _stdcall function.
    You must replace this declaration by
    Code:
    typedef void (__stdcall *myfunc)(void);
    You don't need dynamic linking, instead you need a .def file to convert the VC style name mangling to GCC name mangling:
    Code:
    ; .Def file
    IMPORTS
    func1@0=NameOfTheDll._func1@0 ; you should not use absolute dll path, but only the dll name.
    And declare in a header file the func1 function:
    Code:
    #ifdef __cplusplus
    #define EXTERN_C extern "C" // avoid C++ style name mangling
    #else
    #define EXTERN_C
    #endif
    
    #define Import(type) EXTERN_C type __stdcall
    
    Import(void) func1(void); // with a C++ file, it is expanded to : extern "C" void __stdcall func1(void);
    You must pass the .def file to the linker or to gcc.exe or g++.exe if you use a single-step compilation (g++.exe automatically call the linker if the -c option is not used).
    If you use DevCpp, you must go to Project menu/Project options menu item/parameters tab/linker text box, and enter the name of the .def file.
    Last edited by SuperKoko; June 3rd, 2005 at 12:02 PM.

  3. #3
    Join Date
    Apr 1999
    Posts
    27,449

    Re: GCC, dynamic linking and calling conventions

    Quote Originally Posted by Hobson
    Hello

    I am trying to develop Windows application using DevCpp and GCC compiler v.3.2.4. Application uses mylib.dll library compiled with MSVC 7 and this causes the incompatibility problems. Some functions (almost all) at mylib.dll use __stdcall calling convention, while GCC compiler uses __cdecl by default. This behaviour can be changed globally using -mrtd switch.
    As SuperKoko pointed out, all you need to do is declare whatever function you want to declare as either __stdcall or __cdecl -- you don't need a global switch.

    As far as I know, all Windows C++ compilers allow you to individually declare functions as either __stdcall or __cdecl.

    But to be perfectly honest with you -- unless the compiler comes with a "lib" generating tool, where you can just take the DLL and make a compatible import library for the compiler (i.e. IMPLIB.EXE from Borland), I don't bother with figuring out def files, lib files, etc. Every compiler has their quirk as to how to implicitly link to a library, and I don't have the time or patience to figure out each one.

    Instead I use LoadLibrary() and GetProcAddress() in a convenient class wrapper. Then there is no need to be fooling around with creating lib files, def files, and best of all, the link issues disappear (just make sure you declare your functions correctly). Not only that, the app will compile on any Windows compiler with little to no modifications.

    Regards,

    Paul McKenzie

  4. #4
    Join Date
    Dec 2004
    Location
    Poland
    Posts
    1,165

    Re: GCC, dynamic linking and calling conventions

    Thanks guys for your replies.

    Id like to stick to dynamic linking, and not to bother with all those files needed every time I switch compiler. Just DLL and source is what I want.
    Unfortunately, none of methods mentioned by SuperKoko did not work. Declaring pointer as
    Code:
    void (_stdcall *myfunc)()
    does not help, there is still a runtime error. After creating .def file with altered names linker complains about undefined reference.

    Maybe there is something wrong with my code, I am going to look deeper into it.

    Anyway, thanks for help.

    Hob
    B+!
    'There is no cat' - A. Einstein

    Use &#91;code] [/code] tags!

    Did YOU share your photo with us at CG Members photo gallery ?

  5. #5
    Join Date
    Feb 2005
    Location
    Normandy in France
    Posts
    4,590

    Re: GCC, dynamic linking and calling conventions

    Can you post a message attaching the files of your project, and the DLL used?

  6. #6
    Join Date
    Dec 2004
    Location
    Poland
    Posts
    1,165

    Re: GCC, dynamic linking and calling conventions

    Here are apps I am trying to make working. Both client and server suffer the same problem, but thats the server which crashes first (cant pass correctly even single loop). Both apps compiled with VS 6 work ok, but crash when compiled at DevCpp. I hope that all will be clear for you, but if source codes are just too much mess, leave it and dont waste your time, I will manage somehow.

    Here is the file: http://removed, prolem solved

    And there is still some more issues, like not unloaded libraries and so on, but first id like to make calling stuff working.
    Id like to keep main file modified as little as possible, since it should compile on both windows and linux using GCC.
    Thanks a lot
    Hob
    Last edited by Hobson; June 7th, 2005 at 04:56 AM.
    B+!
    'There is no cat' - A. Einstein

    Use &#91;code] [/code] tags!

    Did YOU share your photo with us at CG Members photo gallery ?

  7. #7
    Join Date
    Apr 1999
    Posts
    27,449

    Re: GCC, dynamic linking and calling conventions

    Quote Originally Posted by Hobson
    Thanks guys for your replies.

    Id like to stick to dynamic linking, and not to bother with all those files needed every time I switch compiler. Just DLL and source is what I want.
    Then what you need to do is first establish the calling convention of the exported functions. If they're stdcall, the following macro works across compilers that I've come across:
    Code:
    #ifdef USE_STDCALL
       #define DLLENTRY_DEF __stdcall
    #else
        #define DLLENTRY_DEF __cdecl
    #endif
    
    //...
    // exported DLL function
    typedef void  (DLLENTRY_DEF *MYDLLFUNC1)(LONG, LONG);
    typedef int (DLLENTRY_DEF *MYDLLFUNC2)(LPCSTR);
    // etc..
    The USE_STDCALL would be a user-defined compiler constant that would be set on the compiler's command line (for GCC, this is the -D option).

    Now you define your function pointers (somewhere):
    Code:
    MYDLLFUNC1  pGetListOfNames=NULL;
    MYDLLFUNC2 pGetListOfAddresses=NULL;
    Now you assign to them after calling LoadLibrary()
    Code:
    HMODULE hMod = LoadLibrary("MyDLL.DLL");
    if  ( hMod )
    {
         pGetListOfNames = (MYDLLFUNC1)GetProcAddress(hMod, "GetListOfNames");
    
         pGetListOfAddresses = (MYDLLFUNC2)GetProcAddress(hMod, "GetListOfAddresses");
    }
    Of course, you call FreeLibrary() when you're finished with the DLL.

    I've done it so this is in a convenient class wrapper, but nothing stops you from doing this in just a straight procedural manner.

    Using this method, this works universally across all Windows-based C++ compilers that I've come across. I've tried this with VC++ (all versions), GCC, Borland, CodeWarrior, Digital Mars, Intel C++, you name it. This is the advantage of just investing some time in creating the interface to the DLL at runtime instead of trying to figure out def files, lib files, import libraries, etc.

    My company has to deal with different compilers and versions, and as stated before, trying to figure out how each one implicitly links DLL's was more of a time waster. It is far easier just to take code, compiling it, and just running it if we want to test one of our DLL's.

    Regards,

    Paul McKenzie

  8. #8
    Join Date
    Dec 2004
    Location
    Poland
    Posts
    1,165

    [Solved] GCC, dynamic linking and calling conventions

    amagad, guys, I found a source of my problems. Here comes the explanation, as it could be useful for someone someday.

    1. I declared my function pointers in following way:
    Code:
    typedef void (__stdcall *func)(void);
    2. GCC defines __stdcall as
    Code:
    #define __stdcall __attribute__((__stdcall__))
    3. And now, most funny part: 3rd party library I was using (Apache APR), defined:
    Code:
    #define __attribute__(__x)
    So, __stdcall from my declarations just vanished.

    That was lotta time I wasted for this and I was pretty sure that its not a compiler trouble, but couldnt find the reason of this strange GCC behavior. I managed to find the bug using -save-temps and digging thru 1.6MB of code :/

    anyway, thanks for any help guys, it was really precious

    Hob
    Last edited by Hobson; June 7th, 2005 at 04:47 AM.
    B+!
    'There is no cat' - A. Einstein

    Use &#91;code] [/code] tags!

    Did YOU share your photo with us at CG Members photo gallery ?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured