RFC STDCALL for 32bit Windows APIs
Tobias Burnus
burnus@net-b.de
Tue Nov 13 20:35:00 GMT 2007
Hi all,
since the topic comes up again and again, e.g. at
http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/19d77dfc75f8be58
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31073
http://gcc.gnu.org/ml/fortran/2007-03/msg00162.html
http://gcc.gnu.org/ml/fortran/2007-08/msg00179.html
The problem is that for calling the Windows API on 32bit Windows, one
needs a special calling convention. Other libraries under Windows use
the normal C convention as does 64bit Windows.
I think we should try to give access to STDCALL on 32bit Windows.
Quoting from Steve Lionel of Intel
http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/19d77dfc75f8be58
> On 32-bit Windows, there are two calling conventions, C and STDCALL.
> They differ in one way only - who pops the arguments off the stack.
> With the C convention, the caller does this after the called routine
> returns, whereas with STDCALL, the called routine does this at exit
> (using a variant of the RET instruction that also adds to the ESP
> register (stack pointer.)) STDCALL is a tiny bit faster, but requires
> that you always call the routine with the same number of arguments
> pushed on the stack. All Win32 API routines are STDCALL, and calls
> out of Visual BASIC, Excel, etc. always use STDCALL.
>
> Because it is critical that the caller and callee agree on the number
> of arguments (actually, number of bytes pushed on the stack),
> Microsoft created a naming convention for STDCALL routines where the
> @n suffix is added. The value of n is the number of bytes expected to
> be pushed and popped on the stack. The idea is that if there is a
> mismatch, the linker will complain of an undefined reference. It also
> allows you to create variants of a routine expecting different numbers
> of arguments, each will have a different @n suffix.
>
> You want to call some Win32 API routines from Fortran. These are
> STDCALL routines and their global symbols have the @n suffix.
> Compilers which support STDCALL will automatically add the proper @n
> based on the number and type of arguments the routine expects. This
> information can be provided in an explicit interface, or just from the
> argument list of a call. If the compiler's default is to use the C
> convention, as is the case for gfortran, Intel Fortran, MSVC and
> others, you have to have some way to let the compiler know to use
> STDCALL instead. In most cases, the compilers have a command line
> switch that will change the default for all calls, but most also have
> some sort of syntax that lets you specify this on a per-routine basis.
> In MSVC, it's the __STDCALL prefix, in Intel Fortran it's !DEC$
> ATTRIBUTES STDCALL.
>
> You attempted to use BIND(C) to declare the Win32 API routine, but
> because gfortran assumes the C convention, it properly does not add
> the @n suffix. If you try to "paper over" this by manually adding the
> @n (which you say gfortran doesn't let you do but g95 does), then you
> have circumvented the protection put in place to prevent stack
> corruption in your application. You may not notice it, or you may get
> unpredictable results somewhere down the road after the call returns.
Added by James Van Buskirk:
> The -mrdt switch causes gfortran and g95 to use the STDCALL
> convention. The equivalent on ifort would be /iface:stdcall.
And Steve Lionel again:
> I now see that you used the -mrtd switch for gfortran. I did not
> recognize that earlier. Given that, I would say that gfortran should
> have decorated the name on its own the way a C compiler would have if
> a similar option was used (such as MSVC's /Gm). That you can't
> explicitly specify the @n suffix is another issue, but I maintain that
> the BIND name is not the proper place for that.
Thus there are a couple of questions left:
a) Should the compiler automatically add the "@n" suffix with -mrtd ?
(what does C?)
b) (Esp. if not) should one allow the @ in BIND(C,name=) ?
c) Should we implement "!DEC$ ATTRIBUTES STDCALL" ?
For (b) I would favour a no and for (c) a yes.
Tobias
More information about the Fortran
mailing list