Interface with C
John van Groningen
johnvg@cs.kun.nl
Tue, 9 Jun 1998 11:33:21 +0200
Alan Grover wrote:
>Certainly there is a place to specify the libraries you want to link to.
>But the "code" keyword and the way you specify the interface is not quite
>clear to me. Here is an example from the existing interfaces for the Mac:
>
>SizeWindow :: !WindowPtr !Int !Int !Bool !*Toolbox -> *Toolbox;
>SizeWindow theWindow w h fUpdate t =3D code
>(theWindow=3DD0,w=3DD1,h=3DD2,fUpdate=3DD3,t=3DU)(z=3DZ){
> call .SizeWindow
>};
On the PowerMac there are 2 low level interfaces, the interface to the=
toolbox that was implemented for the 68k to call OS functions and a C=
interface that is similar to the C interface for other processors. The=
toolbox interface uses 'code (inputparameters)(outputparameters){' followed=
by a 'call' and sometimes some 'instruction 0xhexdigits' lines. The C=
interface uses 'code {' followed by a 'ccall' instruction.
The characters after an input parameter name and =3D describe the interface:
W means push a word (16 bits) on the stack.=20
L means push a long word (32 bits) on the stack.
Dn means move the parameter to register 3+n (on the PowerPC). The calling=
convention use by the C compiler passes the first argument in r3, the next=
in r4, ... So D0 is the first argument, D1 is the second,..
U means not used.
>For you non-Mac people, Toolbox is an environment for the Mac API. I've
>deduced that the "code" associates the arguments with the PowerPC registers
>as appropriate for the call. The "t" and "z" aren't part of the real
>SizeWindow function. I haven't spent enough time to figure out what "t=3DU"
>and "z=3DZ" is for (oh, "t" is the Toolbox). Also, I don't have the
>references that tell what registers are used for what. Also, I do not know
>the calling conventions on the PPC (I used to know them for the 68k), so I
>don't know how to call my own C routines.
Z for output parameters means the result is zero. The names of the output=
parameters are irrelevant.
C functions can be called in the following way:
f :: !Int !Int -> Int;
f a b =3D code {
ccall f "II-I"
}
will call:
int f (int,int);
g :: !Int !Int -> (!Int,!Int);
g a b =3D code {
ccall g "II-II"
}
will call:
void g (int,int,int*,int*);
To pass a string to C use S instead of I in the last parameter of ccall. In=
C you get a pointer into the Clean heap. This pointer points to a 32 bit=
length value, followed by the characters.
We are working on a tool that will generate these low level c interfaces=
from a .h file with some additional type information in Clean.
>Here is a slightly more interesting one, showing some inline assembly:
>
>NewWindow :: !Ptr !Rect !{#Char} !Bool !Int !WindowPtr !Bool !Int !*Toolbox
>-> (!WindowPtr,!*Toolbox);
>NewWindow wStorage (left,top,right,bottom) title visible procID behind
>goAwayFlag refCon t
>=3D code (right=3DW,bottom=3DW,left=3DW,top=3DW,wStorage=3DD0,title=3DO0D1S=
D2,visible=3DD3,
> procID=3DD4,behind=3DD5,goAwayFlag=3DD6,refCon=3DD7,t=3DU=
)
>(window_pointer=3DD0,z=3DI8Z)
>{
> instruction 0x7CC600D0 | neg r6,r6
> instruction 0x7D2900D0 | neg r9,r9
> call .NewWindow
>};
>
>What the heck is that "00D1SD2"?
O0D1 means load the stack offset stackpointer+0 in register r4 (3+1).
SD2 means load the address of the pascal string in register r5 (3+2). This=
address is the address of the string in the heap + 7. The first byte is the=
length mod 256, the next bytes are the characters of the string. There is=
no '\0' at the end.=20
I8 means increase the stackpointer by 8.
Rn means decrease the stackpointer by n (reserve stack space).
John van Groningen