This site contains older material on Eiffel. For the main Eiffel page, see http://www.eiffel.com.

 The Eiffel Support Pages 

Using external functions from Eiffel

This note complements the basic information on calling external functions from Eiffel, as given in chapter 24 of the language reference, Eiffel: The Language

For any advanced use of C with Eiffel you should also be familiar with Cecil library, for which an and the on-line presentation is also available.

Eiffel and C types

When incorporating external C functions into an Eiffel system you may rely on the macros and functions defined in $EIFFEL4/bench/spec/$PLATFORM/include/eiffel.h

Do not make any assumptions on the compatibility between Eiffel types and C types (for instance, an Eiffel integer is not guaranteed to be equivalent to a C int). When the C side uses arguments coming from the Eiffel side, it should first, for safety and portability, cast them into types that are guaranteed to work properly. Here are some of the mappings of Eiffel types to C types (defined in $EIFFEL4/bench/spec/$PLATFORM/include/portable.h):

	Eiffel					C

	INTEGER					EIF_INTEGER
	BOOLEAN					EIF_BOOLEAN
	CHARACTER				EIF_CHARACTER
	REAL					EIF_REAL
	DOUBLE					EIF_DOUBLE

	OBJECT					EIF_REFERENCE
	PROCEDURE				EIF_PROC

To pass the address of an Eiffel routine to C, you must use the $ operator. The resulting type on the C side is EIF_PROC.

Passing Eiffel objects to C

There are two ways to pass an Eiffel object to the C side. You must remember that the adress of an Eiffel object may change during garbage collection cycles. Therefore it is not always safe to pass the actual adress of an Eiffel object to the C side (it might not remain valid throughout the entire life of an application).

By default, when you pass an Eiffel object to an external routine, you do not receive the "raw" address to the object on the C side, but a "protected" reference to the address. That reference is managed by the run-time, and updated whenever necessary. The type of the protected reference on the C side is EIF_OBJ.

To access the actual object you must call the routine eif_access. Note that the Eiffel object is only protected until the end of the call to external routine. If you wish to have a permanent protection on an Eiffel object you must use the eif_adopt function (which takes an EIF_OBJ as argument and returns and EIF_OBJ).

You may pass the "raw" address of an Eiffel object to C by using the $ operator, but in that case you must be sure that the object will not move in memory because of the garbage collector.

Note that you cannot combine the $ operator with dot (.) notations.

Example 1

External C function performing a multiplication of integers:

    C side

      EIF_INTEGER mult (a, b)
      EIF_INTEGER a;
      EIF_INTEGER b;
      {
      	return (EIF_INTEGER) ((int) a * (int) b);
      }
      

    Eiffel side

      mult (a, b: INTEGER): INTEGER is
      	external
      	"C"
      	end
      

Example 2

Calling an Eiffel routine from C:

    Eiffel side

      class EXAMPLE
      
      creation
      
      	make
      
      feature
      
      	make is
      		do
      			to_c (Current, $f);
      			call_c
      		end;
      
      	f is
      		do
      			io.pustring ("Hello%N")
      		end;
      
      feature -- External
      
      	to_c (obj: EXAMPLE; proc: POINTER)
      		external
      			"C"
      		end;
      
      	call_c is
      		external
      			"C"
      		end
      
      end
      

    C side

      #include "eiffel.h"
      
      EIF_OBJ eiffel_object;
      EIF_PROC eiffel_procedure;
      
      void to_c (obj, proc)
      EIF_OBJ obj;
      EIF_PROC proc;
      {
      	eiffel_object = eif_adopt (obj);
      	eiffel_procedure = proc;
      }
      
      void call_c ()
      {
      	(eiffel_procedure)(eif_access (eiffel_object));
      			/* Here you need to pass the Eiffel object */
      }