This section describes calling conventions used by the Visual Eiffel compiler for external routines.
1. Kinds of external routines
2. External routine names
3. Hidden parameters
4. Result of functions
5. Summary
The following kinds of external routines are supported:
So, you can define Eiffel routines like this:
do_something is -- This routine is external external "CWC" end
The external routines "C ...", where "..." is an arbitrary string, are processed as being plain "C" routines, though the warning is generated.
Visual Eiffel takes special care about names of external routines to simplify access to them from Eiffel. The primary name of an external routine is either the name mentioned in "alias" clause or the name of the Eiffel routine if the "alias" clause is missing.
do_something is -- Primary name for this external routine is "do_something" external "C" end do_something is -- Primary name for this external routine is "do_nothing" external "C" alias "do_nothing" end
The primary name of external routine is used to produce the real name of the routine, i.e. the name which would be used in object code.
The transformations of the primary name depend on which kind of external routine is used. The following rules are applied:
<effective_name> ::= "_"<primary_name>
<effective_name> ::= <primary_name>
<effective_name> ::= "_"<primary_name>"@"<N>
Example:
For the routine declared as
foo (x, y: INTEGER) is external <kind> end
the following effective names will be generated for different values of <kind>:
"C" | "_foo" |
"CWC" | "_foo" |
"PASCAL" | "foo" |
"WINAPI" | "_foo@8" |
Special naming convention is provided for external "CWC" routines when the Current object is of expanded type (see below).
The only case when the extra parameters are passed to the external routine is "CWC" routine ("CWC" denotes "C-language With Current"). "Current" is passed to that routine as the first parameter. The way of how it's passed depends on the type of the Current: reference or expanded. For reference Current the pointer to the object is passed as a first parameter of the routine.
Example.
Declaration in C for the routine declared in Eiffel as "CWC" in the previous example should look as follows:
void foo (EIF_CURRENT current; INTEGER x, y);
The first parameter is a pointer to the current object.
If the current object is of expanded type, name of the external routine is automatically changed by adding suffix "_ec" (Expanded Current) to its end. Moreover, two hidden parameters are passed rather than one (in the case of reference Current): the first is a pointer to the expanded object and the second is a magic number of the class of this object.
Example:
The declaration in C for the routine from the example above for the expanded object should look as follows:
void foo_ec (void * current; INTEGER magic_number; INTEGER x, y); /* Here */ /* "current" is a pointer to the first byte of expanded object */ /* "magic_number" is a magic number of the corresponding class */
The external routine that is declared as returning basic Eiffel type should return appropriate C type defined in CECIL.
Example:
C declaration for external functions
foo: INTEGER is external "C" end -- This function returns result of basic expanded type bar: DOUBLE is external "C" end -- This function returns result of basic expanded type
should look like
EIF_INTEGER foo (); /* The function should return basic CECIL type */ EIF_DOUBLE bar (); /* The function should return basic CECIL type */
The expanded result that occupies 1 or 4 bytes is returned as a primitive C type of size 1 or 4 respectively.
Example.
C declaration for the external function
foo : X is external "C" end -- This function returns 1-byte result of expanded type
should look like
char foo (); /* The function should return 1-byte result */
Otherwise, it is always assumed that the external routine returns a result of the reference type no matter how it was declared: as returning the reference type or the expanded one.
Example.
C declaration for external functions
foo: ANY is external "C" end -- This function returns result of reference type bar: expanded ANY is external "C" end -- This function returns result of expanded type
should look like
EIF_REFERENCE foo (); /* The function should return reference type */ EIF_REFERENCE bar (); /* The function should return reference type as well */
The only exception is "WINAPI" external function the result of which is treated as being the expanded one. In this case you will get the expanded object which was returned by external function or a copy of it.
Example.
C declaration for external functions
foo: ANY is external "WINAPI" end -- This function returns result of reference type bar: expanded ANY is external "WINAPI" end -- This function returns result of expanded type
should look like
EIF_REFERENCE WINAPI foo (); /* The function should return reference type */ void * WINAPI bar (); /* The function should return pointer to expanded object itself */
All conventions supported by Visual Eiffel for external routines are summarized in the tables below.
Table 1. Naming conventions
Convention | Declaration [for expanded Current] | |
---|---|---|
object file | C | |
"C" or "C ..." | _<name> | <name> (args) |
"CWC" | _<name> | <name> (current, args) |
[ _<name>_ec ] | [ <name>_ec (current, magic, args) ] | |
"PASCAL" | <name> | PASCAL <name> (args) |
"WINAPI" | _<name>@<arg_size> | WINAPI <name> (args) |
Table 2. Function result conventions
Convention | Result type for given Eiffel type | |||
---|---|---|---|---|
basic | 1 or 4 bytes expanded | reference | expanded | |
"C" | primitive | primitive | reference | reference |
"CWC" | primitive | primitive | reference | reference |
"PASCAL" | primitive | primitive | reference | reference |
"WINAPI" | primitive | primitive | reference | expanded |