Sather - A Language Manual - Interfacing with ANSI C

[back] [Abstract] [Copyright Notice] [Contents] [next]

# Sather - A Language Manual - Chapter 14
Interfacing with ANSI C

This chapter describes interfacing with ANSI C , X3.159-1989. See Overall Organization, section 14.1 for a short overview of the C interface functionality. See Built-in C classes, section 14.2 for a introducion on built-in C types provided by the extended Sather library. In User-defined External C types, section 14.3 you find information about user defined external C types, constants, attributes, and shared elements. Parameter Passing, section 14.4 covers parameter passing issues, and finally Inlining C Code, section 14.5 describes the inline C facility.

## 14.1 Overall Organization

An external class which interfaces to ANSI C is designated with the language identifier '`C`'. Types defined by external C classes are called external C types. Similar to external Fortran types, signatures without bodies (abstract signatures) are allowed in external C types. Such signatures must contain only built-in or user defined C types and they are implemented externally in ANSI C. Abstract iterator signatures are not allowed in external C classes. Routines with bodies whose signatures contain only C types may be called from C. Routines with bodies whose signatures use types other than C types are regular Sather routines and are not accessible from C. External C routines cannot be overloaded.

In contrast with the external Fortran classes, external C classes may have attributes and objects of external C types may exist. All attributes must also be of C types. The C interface provides a naming facility that allows interoperability with the existing C header files.

Global C variables can be accessed as shared attributes of external C classes.

C symbols are generated by applying a platform specific C name binding convention to the textual external C routine names. It is also possible to explicitly specify name binding for external C classes.

Finally, it is possible to inline ANSI C code into Sather sources. This allows for even greater flexibility in achieving Sather/C interoperability.

## 14.2 Built-in C classes

The following C types are built into the extended library:

    Sather Class          ANSI C type
    -------------------------------------
    C_CHAR                char
    C_CHAR_PTR            char *
    C_UNSIGNED_CHAR       unsigned char
    C_UNSIGNED_CHAR_PTR   unsigned char *
    C_SIGNED_CHAR         signed char
    C_SIGNED_CHAR_PTR     signed char *
    C_SHORT               short
    C_SHORT_PTR           short *
    C_INT                 int
    C_INT_PTR             int *
    C_LONG                long
    C_LONG_PTR            long *
    C_UNSIGNED_SHORT      unsigned short
    C_UNSIGNED_SHORT_PTR  unsigned short *
    C_UNSIGNED_INT        unsigned int
    C_UNSIGNED_INT_PTR    unsigned int *
    C_UNSIGNED_LONG       signed long
    C_UNSIGNED_LONG_PTR   unsigned long *
    C_FLOAT               float
    C_FLOAT_PTR           float *
    C_DOUBLE              double
    C_DOUBLE_PTR          double *
    C_LONG_DOUBLE         long double
    C_LONG_DOUBLE_PTR     long double *
    C_PTR                 void *
    C_PTRDIFF_T           ptrdiff_t
    C_SIZE_T              size_t

Variable of the built-in types are binary compatible with the corresponding C types. These classes define appropriate creation routines which may be used for convenient casting between Sather and C types. Also, many basic operations on the built-in C types are provided by the library. For example, it is not necessary to call external C code to add two C_INT variables. All operations on built-in C types defined by the library have the ANSI C semantics. Syntactic sugar for the built-in C types is defined exactly as for "regular" Sather classes.

    -- "basic" operations may be done in Sather
    a:C_LONG := #(10);
    b:C_LONG := #(5);
    c::= a + b;
    #OUT + c.str + " should be 15\n";

'`AREF{T}'` defines a routine '`array_ptr:C_PTR`' which may be used to obtain a pointer to the first item in the array portion of Sather objects. The external routine may modify the contents of this array portion, but must not store the pointer; there is no guarantee that the pointer will remain valid after the external routine returns. This restriction ensures that the Sather type system and garbage collector will not be corrupted by external code while not sacrificing efficiency for the most important cases.

The following example shows how a Sather array could be passed to external C functions:

    /* ANSI C prototypes for functions called from Sather */
    void clear(void* p, int size);
    void better_clear(int *, int size);

    external C class PROCESS_ARRAYS is
       -- routines implemented externally in C that zero
       -- all elements in an integer array of a specified size
       clear(p:C_PTR, size:C_INT);
       better_clear(p:C_INT_PTR, size:C_INT);
    end;

    -- This code demonstrates how to call external C routines
    a:ARRAY{INT} := #(10);
    -- this call just passes an array portion and avoids typecheking
    -- This is not recommended ("a" could be of type ARRAY{CHAR} and the
    -- call would still compile resulting in a runtime error)
    PROCESS_ARRAYS::clear(a.arr_ptr, #(a.size);

    -- this is a better sequence achieving the same result
    -- if "a" is not an array of integers, an error is reported
    PROCESS_ARRAYS::better_clear(#C_INT_PTR(a), #(a.size));

The second call is type-safe. It exploits the constructor for C_INT_PTR that allows creation from ARRAY{INT}.

## 14.3 User-defined External C types

User-defined external C classes are used for multiple purposes. C routines in external C classes implement Sather/C and C/Sather call interfaces. In addition, objects of external C types could be created and passed to or received from C. C global variables are accessed from Sather as shared attributes of external C classes.

### 14.3.1 Constants and C binding names

Constants are allowed in external C classes. The rules for constant initialization are the same as for constants in "regular" Sather classes.

There are two constant features of external C classes that have a special semantics. If present, the `STR` constant '`C_name`' may be used to force a particular C declaration for an external C type. Similarly the `STR` constant '`C_header`' may be used to specify a list of C header files that should be included in each file in which the C declaration appears.

The STR constant 'C_name' provides a C binding name for the type in which it occurs. The STR constant 'C_header' must be initialized to a space separated list of header files (the standard C notation <foo.h> is allowed). Note that if constants C_name and C_header are absent, the Sather compiler generates layouts for the external C objects. If they are present, no layouts are generated and the necessary types must be defined in the specified header files. In this case, it is the responsibility of the programmer to ensure that attribute names are exactly as the structure filed names provided by the header files.

Examples

    external C class BAR is
       attr bar_attr_int:C_INT;
       attr bar_attr_float:C_FLOAT;

       -- the constructor is defined in C
       create_bar:BAR;
       -- this routine that does some processing of bar is also
       -- defined in   C
       process_bar(bar:BAR);
    end;

    -- create an object of type BAR by calling an external
    -- C constructor
    bar:BAR := BAR::create_bar;

    -- now pass "bar" back to C from processing
    BAR::process_bar(bar);

In this example, the Sather compiler generates the layout for the external objec BARt. The corresponding C layout and prototypes of C functions that are called from Sather are below:

    typedef struct {
       int integer_field;
       float float_field;
    } *C_BAR;
    /* Note that C names for the type and struct fields could be
       different from the corresponding names in Sather */

    C_BAR create_bar();
    void process_bar(C_BAR bar);

This is a similar example, but an existing C header file is used with Sather code:

    external C class BAR is
       const C_name:STR := "C_BAR";   -- C binding name for the type
       const C_header:STR := "bar.h <stdlib.h>";

       attr integer_field:C_INT;
       attr float_field:C_FLOAT;  -- the constructor is defined in C
       create_bar:BAR;
         -- this routine that does some processing of bar is also
         -- defined in C
       process_bar(bar:BAR);
    end;

    -- code that creates an object of type BAR by calling an external
    -- C constructor and then passes the object back to C
       bar:BAR := BAR::create_bar;

          -- now pass "bar" back to C from processing
       BAR::process_bar(bar);

The C header "bar.h" contains the following:

    typedef struct {
       int integer_field;
       float float_field;
    } *C_BAR;
    /* Note that C names for the type must be exactly as the binding C
       name specified by the C_name attribute.
       also, struct field names must be exactly the same as attribute
       names in the external C class*/

    C_BAR create_bar();
    void process_bar(C_BAR bar);

This creates a Sather type '`X_WIDGET`' which may be used to declare variables, parameterize classes, and so forth. Furthermore, the C declaration used for variables of type '`X_WIDGET`' will be '`struct XSomeWidget *`'. Any generated C file containing any variable of this type will also include '`<widgets.h>`'

    external C class X_WIDGET is
       const C_name:STR := "struct XSomeWidget *";
       const C_header:STR := "<widgets.h>";
    end; -- external class X_WIDGET

### 14.3.2 Attributes and C structs

Attributes and C structs

Attributes may be placed in external C classes; they are interpreted as fields of a C struct. If the layout of the class is generated by Sather (C_name and C_header symbolic constants are absent), then attributes can have any names. If a C layout from a header file specified by C_header is used, attribute textual names must be exactly the same as a struct filed names from a corresponding C type. It is the responsibility of the programmer to ensure this correspondence.

Points to note

- External C class attributes may only have built-in or user-defined external C types.

- Class constants do not contribute anything to the class layouts; all attributes do.

### 14.3.3 Shared Attributes and C globals

Global C variables may be accessed from Sather as shared attributes of external C classes. Such shared attributes must have names corresponding to those of C globals. Similar to constants, shared attributes do not contribute to the storage needed to layout the class objects.

    external C class FOO is
       C_name:STR := "FOO";
       C_header:STR := "foo.h";

       shared foo:FOO:
       attr val:C_INT;

       -- this is implemented in C
       create_foo:FOO;
    end;

    -- accessing a global C variable
    FOO::foo := FOO::create_foo;
    FOO::foo.val := #(10);

    #ifndef _FOO_H_
    #define _FOO_H_

    typedef struct {
       int val;
    } *FOO;

    FOO create_foo();
    #endif  _FOO_H_

    /* in some C file */
    FOO foo;

## 14.4 Parameter Passing

The ANSI C standard prescribes that a copy is made of each call argument and all argument-passing is done strictly by value. To conform to ANSI C, all "in" arguments are passed by value. In the case of the built-in C types, a copy of a variable is passed. In the case of user defined external C types, a pointer to the object is copied and passed by value.

In addition, for extra flexibility, Sather supports `"out"` and `"inout"` argument modes for external C routines. `"out"` and "`inout"` arguments are passed by a pointer to a local, which may be legally modified by the called routine. The Sather implementation guarantee that such modifications cannot be observed until the routine returns. For C routines called from Sather this is guaranteed by emitting special code for the caller. For Sather routines that may be called from C, this is guaranteed by emitting special function prologues for the callee.

## 14.5 Inlining C Code

Sometimes it isn't possible to decide at the time the external C class is written whether a routine will be implemented in the C code with a macro. This presents a portability problem, because the writer of the external class can't know ahead of time whether the routine will be obtained by linking or by a header file. Such petulant cases can be dealt with by the call '`SYS::inlined_C`'. The argument must be a string literal, and is placed directly into the generated code, except that identifiers following '`#`' that correspond to locals and arguments are translated into the appropriate C names.

[back] [Abstract] [Copyright Notice] [Contents] [next]

Sather - A Language Manual