-
June 3rd, 2005, 06:54 AM
#1
[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 [code] [/code] tags!
Did YOU share your photo with us at CG Members photo gallery ?
-
June 3rd, 2005, 12:00 PM
#2
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:
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.
-
June 3rd, 2005, 12:24 PM
#3
Re: GCC, dynamic linking and calling conventions
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
-
June 6th, 2005, 06:02 AM
#4
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 [code] [/code] tags!
Did YOU share your photo with us at CG Members photo gallery ?
-
June 6th, 2005, 06:30 AM
#5
Re: GCC, dynamic linking and calling conventions
Can you post a message attaching the files of your project, and the DLL used?
-
June 6th, 2005, 06:50 AM
#6
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 [code] [/code] tags!
Did YOU share your photo with us at CG Members photo gallery ?
-
June 6th, 2005, 10:15 AM
#7
Re: GCC, dynamic linking and calling conventions
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
-
June 7th, 2005, 04:42 AM
#8
[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 [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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|