Chapter 4 
=========

  Calling C Routines from Eiffel 




4.1 Preliminary remark 
======================



  The language Eiffel  permits calling ``foreign''  routines --- i.e. 
  program   segments  written  in   another  language.  The  language 
  definition does not  specify which languages  are supported in this 
  sense. Our implementation currently only supports the language C as 
  external  language or  more precisely  any  language that  uses the 
  conventions of C  for passing parameters  and returning values. For 
  this reason we shall only discuss C routines in this chapter. 


4.2 Syntax 
==========

  The  syntax  for  the declaration  of  external  routines  has been 
  changed in Eiffel 3.  Therefore we give a  brief survey; the reader 
  should refer to the language definition [me91] for further details. 


  An external routine is declared in  almost the same way as a normal 
  Eiffel routine: 

  name (argument list) : type is 
    require 
       -- preconditions 
    external "C"  
       alias "external_name" 
    ensure 
       -- postconditions 
  end 

  The elements argument list, type,  require, alias and ensure are 
  of course  optional. Where one  would otherwise write  do, once or 
  deferred one  writes instead the  keyword external  followed by the 
  name of the language in which the external routine is written. With 
  the (optional) alias  clause one can  specify the real  name of the 
  external routine. Ordinarily one uses an alias clause whenever 


* The  real  name of  the  external  routine is  not  a  legal Eiffel 
  identifier. 

* Case is important. 

    The first  situation occurs  for example  when the  external name 
  begins  with  an  underscore. Regarding  the  second  situation one 
  should  note that  the Eiffel  compiler transforms  all identifiers 
  into lower case. If the  external name contains upper case letters, 
  then one must give this name in an alias clause. 


  Eiffel/S allows you to specify that an external routine should not
  get current as its first argument by supporting a fictious language
  'CWC' (read as: C Without Current)


  
4.3 Argument passing 
====================

  Suppose we have declared the following procedure in Eiffel: 

  c_routine (arg1 : ETYPE1, arg2 : ETYPE2, ...) 
    external "C" 
      alias "_my_routine" 
    end 

  Here ETYPE? is  some Eiffel type. Then  the corresponding C routine 
  must look as follows: 

  void _my_routine (Current, arg1, arg2, arg3, ...) 
    OBJREF Current; 
    CTYPE1 arg1; 
    CTYPE2 arg2; 
     ... 
    {
     ...
    }

  Note 


  The extra argument Current will be explained below. 


  The translation of ETYPE into CTYPE is as follows: 



                           Eiffel type C type 


                          CHARACTER CHARACTER 

                            INTEGER INTEGER 

                               REAL REAL 

                             DOUBLE DOUBLE 

                            BOOLEAN BOOLEAN 

                            POINTER POINTER

                         all other types OBJREF 



  These types are declared in the include file eiffel.h. Please note 
  that DOUBLE and REAL are the same in Eiffel/S --- that is, floating 
  point numbers with the highest precision supported by the platform. 


Example 


  Eiffel: 

  c_routine (i : INTEGER, w : WINDOW, b : BOOLEAN, p: POINTER) is
    external "C"
    alias "my_routine"
    end


  C: 

  void _my_routine (Current, i, w, b, p) 
    OBJREF Current; 
    INTEGER i; 
    OBJREF w; 
    BOOLEAN b; 
    POINTER p;
    {
    ...
    }


  The following points are important here: 

* The external C  routine has an  extra argument Current.  This is a 
  reference to the object that is executing the call. 

* All types other than  the basic types given  above must be declared 
  as OBJREF --- regardless of whether they are expanded or not! 

* The  Eiffel  address operator $ is  not supported  by  Eiffel/S (see 
  below). 


  
4.4 Return values 
=================

  Let  us  alter the  example  above  to make  our  procedure  into a 
  function. Then the Eiffel resp. C code looks as follows: 


  Eiffel: 

  c_routine (...) : ETYPE is 
    ... 

  C: 

  CTYPE _my_routine (Current, ...) 
    ... 

  The translation ETYPE -> CTYPE is done with the table given above. 


  
4.5 The address operator
======================== 

  The  Eiffel language  definition provides  for an  address operator $ 
  with which one can pass the  physical address of Eiffel features to 
  external routines. There are  two conceivable applications for this 
  operator: 


* If the  address is  the address of  an attribute  then the external 
  routine can manipulate the attribute directly. 

* If the address  is that of a  routine, then one  can call it ``from 
  outside''. 

    Both constructions can  lead to hard  to find programming errors. 
  But  the main  reason that  Eiffel/S does  not support  the address 
  operator  is  that  the interface  classes  described  in  the next 
  chapter  make  it  unnecessary. The  interface  classes  offer much 
  greater  flexibility  in manipulating  Eiffel  objects  and calling 
  Eiffel  routines. In  particular  while an  address  is necessarily 
  static the interface mechanism offers all the advantages of dynamic 
  binding. 



 
4.6 Inside C 
============

  We now come  to the really  interesting part of  this chapter: what 
  can one do with the arguments passed  from Eiffel to C and how does 
  one give back results? 


  First of all one must include in the module containing the external 
  C routine a line 

  include "installation/run3/eiffel.h" 

  where  installation is  the full  path  to the  Eiffel installation 
  directory.  This is  so that  the C  compiler recognizes  the types 
  INTEGER, BOOLEAN, etc. 

  

4.7 Using basic types 
=====================


  The  basic  types  correspond  to  simple  C  types.  One  possible 
  definition is: 

  typedef int             INTEGER; 
  typedef unsigned  char  CHARACTER; 
  typedef unsigned char   BOOLEAN; 
  typedef double          REAL; 
  typedef char            *POINTER;

  We speak  quite intentionally  of a  ``possible'' definition, since 
  this depends  on the  platform. For  example under  MS/DOS the type 
  INTEGER is declared as long int in  order to have a precision of 32 
  bits. 


  One consequence  of this is  that you should  whenever possible use 
  the Eiffel  basic types  and not  those from  C. When  in doubt use 
  explicit type casts: 


Example 
  #include " ... /eiffel.h"

  REAL distance (Current, i, j) 
    OBJREF Current; 
    INTEGER i; 
    INTEGER j; 
    {
    INTEGER sqd; 
    sqd = i * i + j * j; 
    return (REAL) sqrt ((double) sqd); 
    }

  The corresponding counterexample: 

  REAL distance (Current, i, j) 
    OBJREF Current; 
    INTEGER i; 
    INTEGER j; 
    {
    int sqd; 
    sqd = i * i + j * j; /* Error */ 
    return sqrt ((double) sqd); /* Bad style */ 
    }

  The error  here is that  sqd is of  type int, which  may have less 
  precision than  INTEGER. In the  return statement one  should as a 
  matter  of style  insert  an explicit  type  cast as  shown  in the 
  example although it isn't strictly necessary. 


  INTEGER 


  Corresponds to integer  types in C  short, int or  long and can be 
  used as such. 


  CHARACTER 


  Corresponds to unsigned char. 


  BOOLEAN 


  Can only have the values true  and false. The constants with these 
  names are defined in eiffel.h. 


  REAL and DOUBLE 


  Correspond to floating point types in C ( float or double). In our 
  implementation both are declared as double. 

  

4.8 Using special objects 
=========================

  As explained above all  other Eiffel types are  to be declared in C 
  as OBJREF. The only thing you  might find surprising about this is 
  that   ``expanded''  types  apparently  aren't  expanded.  This  is 
  correct;  an  external C  routine  always  gets a  reference  to an 
  object, never the object itself. 


  We begin  by describing  three special  cases that  are particulary 
  important: 


* Strings 

  An object of type STRING contains, among other things, the sequence 
  of characters that comprise the string --- as C string. The runtime 
  system provides  functions with which  you can access  the C string 
  and with which you can convert a  C string into an Eiffel object of 
  type STRING: 


  CHARACTER  *RSTR_seq (string_objref)    
  INTEGER    RSTR_count (string_objref) 
  OBJREF     RSTR_create (c_string) 


  The  first of  these  functions returns  a  pointer to  a  C string 
  (terminated with  '\0'). The second  returns the  length of the 
  string and  the third  generates a  new object  of type  STRING and 
  copies the C string into this object. 

  Be sure always to observe the following rules: 

     * Never apply the functions free or RMM_free or realloc or RMM 
       _realloc to the  result of the  function RSTR_seq and never 
       pass this string to a function that might execute one of these 
       functions on it. The  result of doing so  is likely to be that 
       the program no longer runs correctly. 

     * The  C  string  that  RSTR_create  receives  as  argument is 
       automatically duplicated  --- that is,  the new  object gets a 
       copy of this string. 

  Example 


    OBJREF make_a_string (Current) 

    OBJREF Current; 
    {
    return RSTR_create ((CHARACTER *) "I will be an Eiffel string!"); 
    }

    BOOLEAN contains_a_tab (Current, string) 

    OBJREF Current; 
    OBJREF string; 
    {
    CHARACTER *p; 

    p = RSTR_seq (string); 
    if (p == (CHARACTER *) 0) return false; 
    while (*p (*p != '\t))
      ++p; 

    return (*p ? true : false); 
    }

    These are of course artificial  examples. Such operations can and 
    should be programmed directly in Eiffel! 



  * Arrays 

    An object of type array contains,  among other things, a C array. 
    Since ARRAY is a generic class,  the type of this C array depends 
    on the actual generic parameter. 


    The available runtime functions are: 

    CHARACTER      *RARR_seq   (array_objref)
    INTEGER        RARR_size  (array_objref)
    CHARACTER      RARR_type (array_objref) 


    The first function returns  a pointer to the  C array. The second 
    function  returns  the size  of  the  array and  the  third gives 
    information about the type: 


       'i' if ARRAY [ INTEGER ] 
       'c' if ARRAY [ CHARACTER ] 
       'r' if ARRAY [ REAL ] or ARRAY [ DOUBLE ] 
       'b' if ARRAY [ BOOLEAN ] 
       'o' in all other cases. 



    The result of RARR_seq must be  cast to a pointer of the proper 
    type: 


    (INTEGER  *)    if ARRAY  [  INTEGER  ] 
    (CHARACTER  *)  if  ARRAY [ CHARACTER ]
    (REAL  *)       if  ARRAY [  REAL  ] or  ARRAY [  DOUBLE ] 
    (BOOLEAN *)     if ARRAY [ BOOLEAN ]
    (OBJREF *)      in all other cases. 


  Example 


    void how_to_access_an_array (Current, obj_arr, real_arr) 

    OBJREF Current; 
    OBJREF obj_arr;
    OBJREF real_arr; 
    {
    INTEGER i, size; OBJREF *op; REAL *rp; 

    size = RARR_size (obj_arr); op = (OBJREF *) RARR_seq (obj_arr); 
    if (op != (OBJREF  *) 0)
    {
       ++op; /* Because  index 0 cannot be used */ 

    for (i = 1; i <= size; ++i, ++op) 
       ... do something with "*op" 
    }
    size = RARR_size (real_arr); 
    rp = (REAL *) RARR_seq (real_arr); 

    if (rp != (REAL *) 0) 
    {++rp; /* Because index 0 cannot be used */ 

    for (i = 1; i <= size;  ++i, ++rp) 
       *rp += 100.99; /* For example */ ... 
    }
    }

    Be sure always to observe the following rules: 

     * Never apply the functions free or RMM_free or realloc or RMM 
       _realloc to the  result of the  function RARR_seq and never 
       pass this array to a function  that might execute one of these 
       functions on it. The  result of doing so  is likely to be that 
       the program no longer runs correctly. 



     * Use  only indices  in the  range 1  .. RARR_size  (..). In 
       particular the index 0 in the C array is always taboo! 

    If you should ever need an Eiffel ARRAY that is to be filled by a 
    C routine,  use a  call to  an interface  function to  create and 
    dimension the array. Then  fetch a pointer to  the C array of the 
    object using RARR_seq. 



  * Bit type 

    Bit types, like arrays and  strings, are special since the object 
    reference does not point to the sequence of values (here bits). 


    The following functions are available: 

    CHARACTER *RBIT_seq (bit_objref)  
    INTEGER RBIT_count (bit_objref) 
    OBJREF RBIT_create (c_string) 


    The first returns a pointer to a C array of CHARACTER. This will 
    never be a  null pointer. The  second returns the  number of bits 
    and the third can be used to convert a bit constant (as C string) 
    into an object of type BIT. 



  Example 

    void where_are_the_bits (Current, bit_objref) 

    OBJREF Current; 
    OBJREF bit_objref; 
    {
    CHARACTER *bp, mask; 
    INTEGER i, count, offset; 

    bp = RBIT_seq (bit_objref); /* Will never be NULL!! */ 

    count = RBIT_count (bit_objref); 

    for  (i =  1; i  <= count;  i++) 
    {
    offset  = (i  - 1)  / 8;  
    mask = ((CHARACTER) 128) >> ((i - 1) % 8); 

    printf ("Bit No. %d is %s\n", i, 
                        (bp [ offset ] mask) ? "on" : "off"); 
    }
    }

    This  example  is  of  course  neither  particular  sensible  nor 
    particularly efficient. It does,  however, show how bit sequences 
    are 


    The ith Bit (1 <=  i <= count) is to  be found in the CHARACTER 
    array at position offset, mask. 


    A call of the form 

    RBIT_create ("10101101110") 
    creates an object of type BITS 11 whose bits are set as given. If 
    you need an object  of bit type but do  not want to initialize it 
    with a  string you  should use  the possibilities  offered by the 
    interface classes. 


4.9 Using objects of other types 
================================


  For objects  of types  other than  those just  listed there  are no 
  corresponding  runtime functions.  What does  one  do then,  if one 
  wants to access or modify an attribute of such an object? 

  The simplest and probably  most frequent case is  that one knows in 
  advance the dynamic  type of the  object. In this  case one can use 
  type casting to access the fields of the structure directly. If the 
  dynamic type  is not known  or if  there is a  possibility the type 
  could change, it is  better to use the  interface classes. They are 
  described in the next chapter. 


  
4.10 Accessing attributes 
=========================

  Every object carries its attributes around with it in the form of a 
  C structure. To explain this structure we begin with an 


Example 

  class SOMETHING
 
    feature 
      i : INTEGER 
      c : CHARACTER 
      r : REAL 
      b : BOOLEAN 
      w : WINDOW 
      s : STRING 
      e : expanded WINDOW 
    end -- class SOMETHING 

  The  Eiffel/S compiler  produces upon  request  (cf. Chapter  2) an 
  include file "something.h" that looks as follows: 

  typedef struct { 
    BOOLEAN   Eb; 
    CHARACTER Ec; 
    OBJREF    Ee; 
    INTEGER   Ei; 
    REAL      Er; 
    OBJREF    Es; 
    OBJREF    Ew;
     
    } ECA_something; 

    #define ECsomething(objref) ((ECA_something *)(objref)) 

  The field names  are precisely the  original Eiffel attribute names 
  with a prepended  `E'. This `E'  makes it possible  to use names in 
  Eiffel that would be reserved keywords in C. Although one would not 
  normally need to make use of  this fact, we mention that the fields 
  are ordered alphabetically. 

  You  can now  manipulate  an object  of  dynamic type  SOMETHING as 
  follows: 


Example 

  include "something.h" 
    void modify_something (Current, obj) 

    OBJREF Current; 
    OBJREF obj; /* Must really be a SOMETHING!!! */ 
    {
    OBJREF window; 
    ECsomething (obj)->Eb = true; ECsomething (obj)->Ei *= 100; 
    window = ECsomething (obj)->Ew; ... 
    }

  The following points must be strictly observed: 

* The dynamic type  must be SOMETHING;  otherwise such manipulations 
  lead directly to desaster. 


* The procedure just described may  not be applied to ARRAYs, STRING 
  s, BITs or  FILEs. These classes have  a special object structure 
  that cannot be manipulated in the way just shown. 

* The object reference may not be void (see below). 

* Attributes that are not of basic type are always declared as OBJREF. 
  This is  true even if  they are expanded.  Eiffel/S never expands 
  subobjects. 



  
4.11 Void tests and assignments 
===============================

  It is often important to test whether an object reference is void. 
  One does this with the test 

  if (objref == VOIDREF) ... 

  A reference can also be set to void with the instruction 

  objref = VOIDREF. 

  VOIDREF is  declared in  eiffel.h as  an external  variable. Please 
  note that the test 

  objref == (OBJREF) 0 

  will always yield false and the assignment 

  objref = (OBJREF) 0 

  is the shortest  route to a  catastrophe! VOIDREF is  in fact not a 
  null pointer but rather a reference to a special object. 


  
4.12 Storing addresses 
======================

  Often it is necessary to store an object reference in a C module as 
  in the following 


Example 

  static OBJREF window; 
    void store_window (Current, w) 
    OBJREF Current;
    OBJREF w; 
    {
    window = w; 
    }

  Doing so can lead to an  error that might easily be overlooked: the 
  garbage collector has no way  of knowing that this object reference 
  is still  needed in the  event that  no part of  the Eiffel program 
  still uses it. Thus  it can happen that  after a garbage collection 
  this reference no longer points to something sensible --- or almost 
  worse, it points to some entirely different object. 

  The solution to  this problem is, however,  very simple: you merely 
  declare the variable as ``protected''. 


Example 


  as above ... 
    {
    window = w; 
    RGAC_protect ( &window, 1); 
    }

  The function  RGAC_protect will  be more  fully described  in the 
  chapter on  runtime functions. This  function is,  however, easy to 
  understand: the object to which  window refers (and recursively all 
  its  subobjects)  are  protected from  elimination  by  the garbage 
  collector. (Put  in a  more technical way:  window is  added to the 
  list of roots of the garbage collector.) 


  If you  should no  longer need  the object  to which  the protected 
  variable refers, you simply write: 

  window = VOIDREF; 

  If you also want to annul the ``protection'', you can write: 

  RGAC_unprotect (&window); 

  Please  note that  you  should never  declare  a local  variable as 
  protected. This leads  to serious --- usually  fatal --- errors! We 
  recommend turning  off the  garbage collector  in external routines 
  --- at least in ones that create new objects. (Cf. Chapter 6) 


