Chapter 5 
=========

Calling Eiffel Routines from C 


5.1 Introduction 
================


  This   chapter  describes  the  possibilities  for  calling  Eiffel 
  routines, manipulating attributes and  creating objects from inside 
  C  routines.  The use  of  these  mechanisms should  always  be the 
  exception. After all,  it is not  our purpose to  write extensive C 
  programs but rather to develop Eiffel classes and combine them into 
  programs. 


  In particular you should resist the  temptation to write parts of a 
  program in C that  could just as well be  written in Eiffel --- for 
  reasons of supposed ``efficiency''. For one thing you will discover 
  that you  hardly gain  anything in the  way of  efficiency. But you 
  definitely loose  all the flexibility  that a  language like Eiffel 
  with inheritance and polymorphism offers --- and the runtime checks 
  provided by Eiffel assertions as well. 


  
5.2 Class and feature names 
===========================

  If  you should  happen  to look  at the  C  files generated  by the 
  Eiffel/S compiler,  you will  discover that  all Eiffel identifiers 
  have been replaced  by numbers. You  will not be  able to tell what 
  Eiffel routines  are in  which modules.  The reason  for converting 
  names into numbers is purely technical and we will not go into this 
  matter here. The consequence, however, is that you will not be able 
  to call any  of the Eiffel  routines directly from  C; you will not 
  know the number and it changes from program to program anyway. 


  A  further reason  why  you might  not be  able  to call  an Eiffel 
  routine  directly  is  that  it may  have  been  eliminated  by the 
  compiler! The Eiffel/S compiler produces  no code for routines that 
  cannot be  reached from the  creation procedure of  the root class. 
  One  could  of  course  think up  some  mechanism  for  telling the 
  compiler  not  to  eliminate certain  routines.  But  the interface 
  classes offer a simpler and more elegant solution. 


  
5.2 Interface classes 
=====================

  Nearly any Eiffel  class can be  used as an  interface class. To do 
  this one  must list the  class in  the interface clause  of the PDL 
  file (see Chapter 2). The  compiler then generates normal names for 
  this class; more  precisely, it retains  the original Eiffel names. 
  Since you now know  the names of the  Eiffel routines, you can call 
  them directly from  C. Moreover the  compiler regards every routine 
  that can be reached from an  interface class as being protected: it 
  may not be eliminated by the optimizer. 


  There are just four --- almost obvious --- restrictions. 


  A class may be  declared as an interface class  in a program if and 
  only if: 

* It is effective (i.e. not deferred). 

* It is not generic. 

* It has no descendents in this program. 

* It is not  one of the classes  INTEGER, BOOLEAN, CHARACTER, REAL 
  or BITS. 

    Thus a call (from  C) to a routine in  this class has exactly one 
  interpretation; redefinition in derived classes has been excluded. 


  
5.4 Using interface classes 
===========================


  To use a class C as interface class you must proceed as follows: 

  1. List the class C in the interface clause of the PDL file. 

  2. The call to a routine r in class C then looks as follows: 

      c_r (Current, arg1, arg2, ...) 

  where Current is an  object reference of type  C that is not void. 
  arg1, etc.  are the  arguments of  the routine  r. Of  course the 
  number and types of the actual arguments must agree with the formal 
  arguments of the Eiffel routine r resp. must conform to them. 

    The  name  under  which  a  routine  of  a  class  is  called  is 
  constructed by concatenating the class  name, an underscore and the 
  name of the routine. All letters must be lower case. 


Example 

  Let us suppose you are writing  an interface to a windowing system. 
  There are  internal Eiffel  windows and  external windows  that are 
  administered (let's  say) by  a C  library. The  connection between 
  these two worlds must be  established through external C functions. 
  Whenever an  event occurs in  an external  window the corresponding 
  Eiffel window has to be informed. 


  Let us suppose for  the sake of this  example that the Eiffel class 
  WINDOW cannot  itself be  used as an  interface class  since it has 
  descendants. Therefore the first  step involves defining a suitable 
  interface class in the Window Cluster: 

  class WIF -- Window InterFace 
    creation 
      make 
    feature 
      make is 
      external "C" 
      alias "cwindows_set_wif" 
      end 
    ... 
    end -- class WIF 

  In the C module we then make the following definitions: 

  include "eiffel.h" 
    ... 
    static OBJREF wif; 
    ... 

  void cwindows_set_wif (Current) 
    OBJREF Current; 
    {
    wif = Current; 
    RGAC_protect ( wif, 1); /* Beware of the garbage collector */ 
    }
    ... 

  Thus we have the possibility of  creating an instance of WIF at the 
  beginning of our  Eiffel program and  ``implanting'' this object in 
  the C module: 

  ... 
      the_wif : WIF 
      !!the_wif.make ... 

  The C  module can now  call any routine  in the class  WIF with its 
  static variable wif as Current. 


  To simplify the example we assume that our C module knows about all 
  Eiffel  windows and  all external  windows  and also  knows exactly 
  which internal window belongs to which external window. 


  Whenever an event occurs  in an external window  a routine in the C 
  module is  called. This routine  must first  determine which Eiffel 
  window is involved  (for example by consulting  a table). Then this 
  window gets a message: 

    ... 
    wif_notify_closed (wif, window) 
    ... 

  Here wif is the instance of the class WIF that was ``implanted'' at 
  the beginning of the  program and window is  the Eiffel object that 
  belongs to the external window in which the event occurred. Here we 
  have supposed that the window was just closed. 


  In the class WIF we then write a routine 

  notify_closed (w : WINDOW) is 
    do 
      w.close 
    end 

  where of course close is a  routine of the class WINDOW that closes 
  a window. 


  In analogous fashion you can  introduce routines in WIF that create 
  a new object and give it back to C or that access an attribute: 

  new_window (width, height : INTEGER) : WINDOW is 
    do 
      !SPECIAL_WINDOW!Result.make (width, height)
    end
 
  width (w : WINDOW) : INTEGER is 
    do 
      Result := w.width 
    end 

  (SPECIAL_WINDOW is supposed to be a descendant of WINDOW). 


  This example illustrates that with  a simple and readily understood 
  method  all  ``callbacks''  from C  to  Eiffel  can  be implemented 
  efficiently.  In  particular  you  can  take  advantage  of dynamic 
  binding  as  the  example  with  notify_close  shows,  where  the 
  argument w can have various dynamic types. 


  Technical note 

  Some compilers and some linkers  regard only the first n characters 
  of an identifier as significant, where  n is a fairly small number. 
  If your compiler  or linker has  such a restriction,  then you will 
  have to choose short names for your interface classes and also make 
  sure that the first few characters of each feature in the interface 
  class uniquely determine the feature. 


Example 


  The two features 

  window_class_generic_open 
  window_class_generic_close 

  in the interface class VERY_LONG_CLASS_NAME are sure to cause 
  trouble. In  the C module  generated by the  Eiffel/S compiler they 
  will have the names 

  very_long_class_name_window_class_generic_open 
  very_long_class_name_window_class_generic_close 

  Compiler  and  linker would  have  to  use at  least  the  first 42 
  characters of an identifier to distinguish these two features. 

