FFI Again (last time, I promise!)

Jarvis, Robert P. (Contingent) Jarvisb at timken.com
Tue Oct 17 12:47:51 UTC 2000


>From the Visual C++ documentation:

__cdecl
	Argument-passing order			Right to left 
	Stack-maintenance responsibility	Calling function pops the
							arguments from the
stack 
	Name-decoration convention		Underscore character (_)
							is prefixed to names

	Case-translation convention		No case translation
performed 

__stdcall
	Argument-passing order			Right to left. 
	Argument-passing convention		By value, unless a pointer
							or reference type is
passed. 
	Stack-maintenance responsibility	Called function pops its own
							arguments from the
stack. 
	Name-decoration convention		An underscore (_) is
prefixed
							to the name. The
name is
							followed by the at
sign (@)
							followed by the
number of bytes
							(in decimal) in the
argument
							list. Therefore, the
function
							declared as
							int func( int a,
double b ) is
							decorated as
follows: _func at 12 
	Case-translation convention		None 

There used to be a __pascal calling convention which IIRC was similar to
__stdcall except that arguments were pushed from left to right, there
was no name decoration, and case was always translated to uppercase;
however,
this is no longer supported (at least by Visual C++).

The advantage to __stdcall and __pascal is that the function arguments are
popped from the stack by the called function.  On the x86 architecture the
RET instruction can do both the <return-from-function> and <pop-args-from-
stack> at the same time, thus saving one instruction per function call.
If you were to call a function with 5 bytes of arguments on the stack here's
how the function epilog would look under the different calling conventions:

	__cdecl			__stdcall/__pascal

	RET 0				RET 5
	.				.
	.				.
	.				.
	<back in the		<back in the
	 calling function>	 calling function>
	SUB SP, 5			...more
	...more			 instructions...
	 instructions...

So basically __stdcall saves you that SUB SP, x instruction after every
function call in the program.  It's not much, but it's something.  Note
that this is tuned to the x86 architecture.  I don't know if other chips
support the 'return-and-pop-arguments' variant of RET.

Under Windows 9x and NT, __stdcall is the standard calling convention.
Under Win 3.x __pascal was the standard (IIRC).  Looking at the VC++
headers it appears that the Mac uses cdecl by default and, true to its
Unix heritage, Linux uses cdecl.

I hope this helps.

Bob Jarvis
Compuware @ Timken

> -----Original Message-----
> From: Kevin Fisher [mailto:kgf at golden.net]
> Sent: Monday, October 16, 2000 7:37 PM
> To: squeak at cs.uiuc.edu
> Subject: FFI Again (last time, I promise!)
> 
> 
> 
> Sorry to bring this up again, but now that I've gotten FFI 
> under UNIX working 
> I've got a question about the calling syntax.
> 
> When creating a method to call an external function, you use 
> something like 
> this in the method definition:
> 
> <cdecl:  long 'system' (char*) module:'libc.so.6'>
> 
> So, the questions:
> 
> 1)  Why does UNIX use <cdecl ...> while Mac and Windows use 
> <apicall ...>?
> 2)  In the above example, I have to use the module 
> 'libc.so.6' specifically, 
> or else the function call won't work.  However, in the X11 
> examples the module 
> is always set to 'X11' (not libX11.so).    Is there any way I 
> can call from 
> the standard C library without specifically having to reference the 
> version-specific libc.so.6?  Using module: 'c' doesn't work...
> 
> Thanks for any advice!
> 
> 





More information about the Squeak-dev mailing list