[Mono-list] PInvoke Conventions

Jay Freeman (saurik) saurik@saurik.com
Wed, 18 Jul 2001 00:39:16 -0500


Calling conventions are just as used on Linux as they are anywhere else,
it's just that so many people on Linux use C (many times for bad reasons)
that it tends to get forgotten.  Hopefully the Mono project will invigorate
people to actually know more than the one programming language and the one
or two scripting languages they feel confortable with (although I doubt it,
people are likely to just keep clammoring for their C).

It is also important to diffentiate between "calling conventions" and
"naming conventions".  Please realize that PInvoke needs to take the latter
into account, which has nothing to do with the "x86 instructions used to
make the call and the order of the parameters".  What happened was that most
languages (BASIC, Forth) were using the "Pascal" calling convention, whereby
the caller pushes his arguments onto the stack, jump and links to the
callee, who uses and then removes the arguments from the stack and jumps
back to the branch point.  This works fine and is an efficient way of doing
things, it means that the code to clean up the stack isn't duplicated among
large numbers of users.

( Note that calling conventions also decide things such as what registers
need to be preserved, the aforementioned "order of the parameters", etc..
I'm only going over the clean-up as that puts forth a _reason_ why C works
the way it does. )

However, C decided it wasn't powerful enough.  C supports something called
"variable arguments", whereby the true number of arguments that was passed
to a function isn't known to it at compile time.  If such a function needed
to clean up its stack, it would be unable to do so.  For this reason C
adopted the C calling convention where the caller has to clear the stack.

WINAPI, which is mentioned, isn't even a calling convention; WINAPI is a
macro which specifies the "standard" calling convention (which is used for
all API calls), and the C "naming convention".  The reason it is included as
part of PInvoke's binding system is for ease of usage and for the
specification of the naming convention.  I believe the "standard" calling
convention uses whichever of the above two calling conventions that is more
efficient (based on whether or not variable arguments are used), although
I've never been in a position where people used this with a variable
argument function so I'm not sure on this.

The biggie here, the naming convention change, once again isn't a Windows
thing, this time it is a C++ thing.  C++ mangles names with extra
information that makes exception handling and the such work without near as
much support glue while C only uses the name of the function.  It also
allows you to import symbols from libraryes that have the same name but
different signatures.  This name mangling makes these functions be exported
as funny name such as:

?SetVideo@ShadeOp@@UAEX_N@Z

:, an example which I pulled from one of the DLLs in our 3D engine.  This
information uniquely defines this member by name, arguments, what class it
is in, I believe even what namespace it is in.  When people complain that
the binary interface to C++ isn't standard, this is usually what they are
complaining about; different compilers tend to do this name mangling process
differently, making it difficult to correctly link.  However, all C++
compilers you will ever come across support 'extern "C"' notation, which
exports the function the way C would, i.e., with just its name.

The obligatory reference and URL to some past project:  A while back I wrote
a COM object that let you bind to Windows APIs from any Windows scripting
host at runtime (was going to use this in the scripting environment for an
IRC client I was writing).  To accomplish this I had the COM object marshal
the types and then use inline assembly to do the actual transitions.  Works
very well, actually, and I'm quite proud of it (someone else was working on
the same thing for quite a while yet I managed to do it in 2 days without
any previous knowledge of assembly).  Its website isn't linked to my main
page anymore, but can be found at:  http://www.saurik.com/apicall/ .

Actually, that's a good point, do we have the ability to do this using .NET?
I might be remembering incorrectly, but I don't think so.  If not, I should
port my library to MC++.

Sincerely,
Jay Freeman (saurik)
saurik@saurik.com


----- Original Message -----
From: "Rhys Weatherley" <rweather@zip.com.au>
To: "Bob Salita" <bsalita@hotmail.com>; <mono-list@ximian.com>
Sent: Wednesday, July 18, 2001 12:04 AM
Subject: Re: [Mono-list] PInvoke Conventions


> Bob Salita wrote:
>
...
> >
> > Ouch. Is there a difference in size depending on CallingConvention type
> > (CDecl, StdCall, WinAPI)? Does one of these match my suggestion?
>
> No.  They just change the x86 instructions used to make the
> call and the order of the parameters.  e.g. flipping between
> C and Pascal style calling conventions.  But my brain is a
> bit rusty on this - I've been on Linux long enough to forget
> most of that stuff, thank God. :-)
>
...
>
> Cheers,
>
> Rhys.