stdcall vs c vs cdecl vs pascal vs whosyerdaddy 
Author Message
 stdcall vs c vs cdecl vs pascal vs whosyerdaddy

I was compiling all this to ask a question, kinda think I answered it
along the way (Pascal means stdcall) but then figured, what the hell,
someday someone struggling with FFI may be searching Google....

MicroSoft MSDN (hissssssss):
"cdecl:
This is the default calling convention for C and C++ programs. Because
the stack is cleaned up by the caller, it can do vararg functions. The
__cdecl calling convention creates larger executables than __stdcall,
because it requires each function call to include stack cleanup code...
[snip]...Because the C naming and calling conventions are the default,
the only time you need to use __cdecl is when you have specified the /Gz
(stdcall) or /Gr (fastcall) compiler option. The /Gd compiler option
forces the __cdecl calling convention."

and:
"The __stdcall calling convention is used to call Win32 API functions.
The callee cleans the stack..."

Corman:
"define-foreign-function:
[parameter]linkage-type should be either :c or :pascal, with :c being
the default. With :c linkage, the called function is not expected to
remove the parameters from the stack when it returns. With :pascal
linkage, it is assumed that the called function will remove the passed
parameters."

[kenny: ok, so Corman :c is MS _cdecl and :pascal is _stdcall]

then under the C->lisp FFI generator:
"pascal
This parameter should be a string or a list of strings (or symbols, in
which case their names are used). Functions that have one of these
tokens in their prototype will have :pascal linkage, other functions
will have the default :c linkage. Very often, working with Win32
declarations, this parameter would have "WINAPI" as its value.

[Kenny: right, "The __stdcall [aka pascal] calling convention is used to
call Win32 API functions" even tho cdecl is the MSVC default.]

Lispworks:
"calling-convention
-------------------
Specifies the calling convention used. :stdcall is the calling
convention used to call Win32 API functions and matches the C
declarator "__stdcall". :cdecl is the default calling convention for
C/C++ programs and matches the C declarator "__cdecl"."

[kenny: thx for not mentioning pascal <g>]

AllegroCL:
"[calling] convention:
This argument allows the specialization of calling conventions due to
language or operating-system distinctions. The default convention is :c,
and is adequate for most situations. (Note that on NT and Windows95 the
c/stdcall convention distinction is required for callbacks using
defun-foreign-callable, but is not required in def-foreign-call)."

[kt: cool, detected automatically?]

"Other than :c, (the default and suitable for most purposes), the
:fortran convention is defined. This convention generally causes a
conversion of most atomic arguments to pass-by-reference."

[kt: thx for not mentioning pascal. now about that "fortran"... <g>]

--

  kenny tilton
  clinisys, inc
  http://www.*-*-*.com/
  ---------------------------------------------------------------
"Cells let us walk, talk, think, make love and realize
  the bath water is cold." -- Lorraine Lee Cudmore



Mon, 15 Aug 2005 03:54:13 GMT  
 stdcall vs c vs cdecl vs pascal vs whosyerdaddy

Quote:

>AllegroCL:
>"[calling] convention:
>This argument allows the specialization of calling conventions due to
>language or operating-system distinctions. The default convention is :c,
>and is adequate for most situations. (Note that on NT and Windows95 the
>c/stdcall convention distinction is required for callbacks using
>defun-foreign-callable, but is not required in def-foreign-call)."

>[kt: cool, detected automatically?]

You don't really need to detect it. If you just stash the esp (stack pointer)
value somewhere (pretty much anywhere but on the stack) before pushing arguments
(or afterward, but storing the value the stack pointer had prior to pushing the
arguments), and then restore it when the call returns, you will be OK. If it was
a cdecl, then restoring esp clears the arguments. If the caller cleared them
(__stdcall), then it's a noop.

The only thing that can be tricky is finding an appropriate place to stash the
stack pointer. If you are not running multi-threaded a global variable will
probably work. Otherwise you need a per-thread slot or a  register. Functions in
Windows are required to maintain edi, esi and ebp (and I think ebx).

However:
Callbacks still need the correct declarations because the caller is not
necessarily going to be as flexible (you don't control it). It is going to
assume you left the stack pointer positioned correctly and may not restore it.

Also, callbacks open up the possibility that you may call into foreign functions
recursively, so the per-thread storage slot becomes a stack, and unwinding can
mess things up. A save register is probably the best bet.

In Corman Lisp I didn't do this, and just prefer to make the foreign function
programmer use the right declaration. Since any errors in the declaration pretty
much wreck the call, it's just one more detail.
Roger Corman
Corman Technologies
www.cormanlisp.com



Mon, 15 Aug 2005 15:43:04 GMT  
 
 [ 2 post ] 

 Relevant Pages 

1. need info on C++ vs Object Pascal vs Objective C vs etc

2. 68K vs CFM68K vs Tk 8.0.3 vs AppearanceLib vs System 7

3. cdecl vs stdcall

4. Win2000, TCL, RPC, and stdcall vs. cdecl

5. MASM vs TASM vs VC++ vs DJGPP vs A*^ vs PCC vs DEBUG,, "Hello World!"

6. MASM vs TASM vs VC++ vs DJGPP vs A*^ vs PCC vs DEBUG,, "Hello World!"

7. ST vs Java vs ST vs ....

8. API vs Internal vs Public vs Private in Envy/QA

9. VO vs DELPHI vs FOXPRO(Windows) vs DBASE(Windows)

10. Cellular automata benchmarks: Java vs C++ vs Java vs C++

11. Cadence NCSIm Vs NCSim Desktop Vs Modelsim Vs VCS

12. Cadence NCSIm Vs NCSim Desktop Vs Modelsim Vs VCS

 

 
Powered by phpBB® Forum Software