[Erlang Systems]

1 Overview

The Interface Generator (IG) is a tool which makes it easier to interface C with Erlang. With IG, it is possible to transparently access the "other" language directly. C functions look like Erlang functions on the Erlang side, and Erlang functions look like C functions on the C side. IG accomplishes this by generating interface stubs on both sides. These stubs will then handle all communication and parameter passing between Erlang and C.

fig1
The IG Generated Stubs

A header file defines the interface for which IG generates stubs. This header file is a real C header file which is included in user's C code. The header file must be augmented with some IG keywords, but it otherwise looks like a normal C header file. The keywords do not disturb normal C header file duties. Currently, IG does not handle the complete ANSI C syntax, but a subset thereof.

IG generates interface stub code on both the Erlang side and the C side. The stub code then takes care of argument marshalling and the routing of function calls. The stub on the Erlang side contains the interface functions and acts as shadow for the "real" C functions. When an Erlang stub function is called, it sends a request for the function call to the C stub. The C stub does the real function call and passes the result back to Erlang. The IG stubs uses the standard Erlang port mechanism for its communication, but this can be changed to sockets if required.

fig2
The Call Chain

Refer to the IG distribution which contains many examples. The reader is recommended to read through and run these examples.

1.1 IG Basics

IG works by generating stub files from a C header file which includes some added IG keywords. Two, and possibly three, files are normally produced:

IG reads the input header file and interprets the keywords which serve as guides for the generator. They are needed because more information than is normally present in a C header file is needed for the stub generation.

The following section provides a quick summary of all the IG keywords and small examples of their use. The examples include most constructs. These examples illustrate what is written in an IG header file.

1.1.1 Keywords Used in Erlang to C Situations

IG_fun
This keyword marks a function as accessible from Erlang. IG_fun int plus(int a, intb); means that the function plus can be called in Erlang.
IG_void
This keyword marks a function as accessible from Erlang, but the function does not return a value. It is a one-way call as shown in the example IG_void void do_it();
/*IG_var*/
This keyword marks a C variable as accessible from Erlang. The function call generates a get and set function in Erlang. Example: /*IG_var*/ extern int my_int;. The variable must be declared extern.

1.1.2 Keywords Used in C to Erlang Situations

IG_call
This keyword marks a function as accessible from C. IG_call int get_time(); is in effect a declaration of an Erlang function.
IG_cast
One-way call of an Erlang function. It is to IG_call what IG_void is to IG_fun. Example: IG_cast void throw_msg(IG_string str);

1.1.3 General Keywords and Types

/*IG*/
The /*IG*/ comment keyword is used together with pre-processor directives. /*IG*/ #define PI 3.14 defines an Erlang macro with the name PI. Note the space after the comment. The definitions are generated to the .hrl file only.
IG_binaryPtr
The C type definition of the Erlang binary type, which can be used to pass large chunks of memory to and from Erlang. This is not really a keyword, but rather an IG type definition. Example: IG_fun IG_binaryPtr get_state();
IG_string
This is used for the C char* type when the type means a character string as opposed to those that are really pointers to bytes. Do not use IG_string when char* denotes a arbitrary pointer to bytes. For example, the declaration IG_fun IG_string get_version_str(); tells IG that the function get_version returns a NULL terminated string so that IG will build an Erlang string of the characters. If char* is used, then IG treats the return value as an opaque pointer instead of trying to build an Erlang string of the characters.
struct
While the struct keyword is not really an IG keyword, IG will generate Erlang records for every struct type declaration it sees. Records are generated to the .hrl file only.

The IG keywords enable IG to generate stubs which handle all communication link set-up, message passing, marshalling of arguments, and return values.

The design philosophy of IG is to make important aspects of C valid in Erlang, and to find solutions which ensure that it feels natural to use C with Erlang.

1.1.4 A Hands-On Example

This section describes an example which might help in understanding the basic behaviour of IG. Readers can skip this section at their own discretion.

This simple example calls the C function foo from Erlang and goes through all steps, from the header file to the final call of foo from Erlang. The first step is to write the header file which defines the interface to foo. We do this in a file called ex1.h which looks as follows:

IG_fun int foo(IG_string name, int age);
    

This means that foo can be called from Erlang. The next step is to write the actual definition of foo. We will place this definition in the file ex1.c which looks as follows:

#include <stdio.h>
#include "ig.h"
IG_fun int foo(IG_string name, int age)
{
  fprintf(stderr, "foo: name='%s', age=%d\n", name, age);
  return age;
}

Note!

We use stderr to print the string because IG uses stdin and stdout for its port communication with Erlang. This can be configured (see also Sockets in Advanced IG Topics).

The stubs are then generated in an Erlang shell:

UNIX> erl
Erlang (JAM) emulator version 4.4.2
 
Eshell V4.4.2  (abort with ^G)
1> ig:gen(ex1).
Calling parser
C symbol allocation...........
Generating C code...........
Generating callbacks
C code generated to file: ex1_stub.c
Generating Erlang code.
Erlang code generated to file: ex1.erl
Generator ready 
ok
2> 
    

We now have an Erlang stub called ex1.erl and a C stub called ex1_stub.c. These must be compiled into an Erlang jam file and an executable file. We begin by compiling the Erlang file in the Erlang shell:

2> c(ex1).
{ok,ex1}
    

The C stub is then compiled and linked into an executable in a Unix shell:

UNIX> gcc -L. -o ex1 ex1.c ex1_stub.c igio.o igmain.o -lerl_interface
UNIX>
    

This produces an executable ex1 which implements the foo function. The ig.h, igio.o, igmain.o, and erl_interface files are part of the IG magic. They contain the declarations, the IO routines, the main loop, and the value representation. These are files from the IG distribution. The reader will have to find the place where IG was installed and then try the usr/include directory for the ig.h file, and the usr/lib for the object files and libraries. We have OTP installed at /home/super/otp/otp_sunos5, so we find the ig.h file in the /home/super/otp/otp_sunos5/usr/include directory.

We are now ready to run the example from Erlang. We start the stubs from Erlang and note that this also starts the C program:

3> P=ex1:start().
<0.22.0>
4> ex1:foo(P, "Nils", 34).
foo: name='Nils', age=34
                        {ok,34}
5> 
    

The foo function has one more parameter than its C counterpart and this is the handle to the C program. The return value is the tuple {ok,34}.

In summary, the steps for using IG are:

  1. write the header file
  2. write the C implementation
  3. generate the stubs
  4. compile the stubs into jam and an executable C program
  5. start the program from an Erlang shell.

Copyright © 1991-98 Ericsson Telecom AB