Jump to content
David Schwartz

'stdcall' for 32-bit vs. 64-bit?

Recommended Posts

for DLL importing, there are lots of {$IFDEF WIN32} stdcall {$ENDIF} constructs I'm seeing.

 

I'm thinking this is for distinguishing between 16-bit and 32-bit library calls.

 

What about 64-bit? Do you need 'stdcall'? Or something else? Or nothing?

Share this post


Link to post

Unlike in 32bit, multiple calling conventions simply do not exist in 64bit.  There is only 1 calling convention, and it is dictated by the 64bit ABI itself.  Keywords like 'cdecl' and 'stdcall' are ignored when compiling for 64bit, so as not to break code that is being ported from 32bit.

Edited by Remy Lebeau
  • Like 1

Share this post


Link to post

The ifdef is pointless and wasteless. On x64 stdcall is, like all calling conventions, ignored. So remove the ifdef and leave stdcall there for the platform that it has meaning. 

  • Like 1

Share this post


Link to post

I ran Dr. Bob's HeadConv to convert several .h files for a DLL to Delphi, and it sprinkles these IFDEFS into all of the function calls. They're needed for older 16-bit stuff, but I haven't run into any in years. It's mainly that I wasn't sure about 64-bit needs. Glad they're no longer of any use in 64-bit mode.

 

Share this post


Link to post

From the code point of view, there is a single calling convention on Delphi for x86_64.

But in practice, on Win64, they may be several calling conventions, e.g;. __vectorcall https://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_vectorcall

This is not yet supported with Delphi - and I doubt it will any day soon, since we have so poor support of vectorization in our compiler. Let's hope a vectorcall; attribute would be implemented someday in Delphi! 🙂

It is supported by FPC - which seems more advanced in terms of optimization and vectorization: https://wiki.freepascal.org/FPC_New_Features_3.2#Support_for_Microsoft.27s_vectorcall_calling_convention

 

Last note: for regular calls, there is a single calling convention per ABI on 64-bit.

But the ABI itself (i.e. how parameters are passed and stack handled) is not the same on Windows and POSIX. The Windows 64-bit ABI differs from the Linux/POSIX/SystemV 64-bit ABI on x86_64.
Check https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions
It won't affect regular pascal code. But if you mess with assembly, ensure you use the right registers and stack alignment!

Share this post


Link to post

Thanks, but in this case, I'm only dealing with Windows and two versions of the same DLL -- a 32-bit and a 64-bit version.

Share this post


Link to post

The default calling convention in Delphi is "register" (the compiler tries to pass parameters in registers if possible to speed things up). 

 

The "Stdcall" convention is used throughout by the 32-bit Windows API (which consists of DLL's).  So, for consistency's sake, it makes sense to adopt that calling convention for your own 32-bit DLL's as well. "Stdcall" tells the compiler that the caller of the function will pass all parameters on the stack in a right-to-left sequence and that the function itself is responsible for cleaning up the stack before returning.

 

As Remy Lebeau pointed out, in 64-bit Windows there's only one calling convention. So you could do something like this:

 

//in the DLL:

Procedure MyProc; {$ifdef win32} Stdcall;{$endif} Export;

begin

..

end;

... exports 'MyProc';

 

 

//In the exe:

Procedure MyProc; {$ifdef win32} Stdcall;{$endif} external 'mydll.dll';

 

 

 

 

 

 

 

Share this post


Link to post
31 minutes ago, A.M. Hoornweg said:

The default calling convention in Delphi is "register" (the compiler tries to pass parameters in registers if possible to speed things up). 

 

The "Stdcall" convention is used throughout by the 32-bit Windows API (which consists of DLL's).  So, for consistency's sake, it makes sense to adopt that calling convention for your own 32-bit DLL's as well. "Stdcall" tells the compiler that the caller of the function will pass all parameters on the stack in a right-to-left sequence and that the function itself is responsible for cleaning up the stack before returning.

 

As Remy Lebeau pointed out, in 64-bit Windows there's only one calling convention. So you could do something like this:

 

//in the DLL:

Procedure MyProc; {$ifdef win32} Stdcall;{$endif} Export;

begin

..

end;

... exports 'MyProc';

 

 

//In the exe:

Procedure MyProc; {$ifdef win32} Stdcall;{$endif} external 'mydll.dll';

 

 

 

 

 

 

 

As discussed above the conditional code simply adds clutter for no benefit. The compiler has already handled the issue for you. Remove the conditional, and let the compiler ignore stdcall in x64.

 

A second point is the use of the export directive. It is also always ignored (a hangover from 16 bit days). Again it should be removed.  Therefore the best practise would be to write:

 

procedure MyProc; stdcall;

And that's it.  Obviously you still need the exports list somewhere.

  • Like 2

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×