7 C Nodes

This section outlines an example of how to solve the example
problem in Problem Example
by using a C node. Notice that a C node is not typically
used for solving simple problems like this, a port is
sufficient.

From Erlang's point of view, the C node is treated like a
normal Erlang node. Thus, calling the functions foo and
bar only involves sending a message to the C node asking
for the function to be called, and receiving the result. Sending
a message requires a recipient, that is, a process that can be
defined using either a pid or a tuple, consisting of a
registered name and a node name. In this case, a tuple is the
only alternative as no pid is known:

{RegName, Node} ! Msg

The node name Node is to be the name of the C node. If
short node names are used, the plain name of the node is
cN, where N is an integer. If long node names are
used, there is no such restriction. An example of a C node name
using short node names is thus c1@idril, an example using
long node names is cnode@idril.ericsson.se.

The registered name, RegName, can be any atom. The name
can be ignored by the C code, or, for example, be used to
distinguish between different types of messages. An example of
Erlang code using short node names follows:

The fourth argument is a pointer to an in_addr
struct with the IP address of the host.

The fifth argument is the magic cookie.

The sixth argument is the instance number.

The C node can act as a server or a client when setting up
the Erlang-C communication. If it acts as a client, it
connects to an Erlang node by calling erl_connect(),
which returns an open file descriptor at success:

fd = erl_connect("e1@idril");

If the C node acts as a server, it must first create a socket
(call bind() and listen()) listening to a
certain port number port. It then publishes its name
and port number with epmd, the Erlang port mapper
daemon. For details, see the epmd manual page in ERTS:

erl_publish(port);

Now the C node server can accept connections from Erlang nodes:

fd = erl_accept(listen, &conn);

The second argument to erl_accept is a struct
ErlConnect which contains useful information when a
connection has been established, for example, the name of the
Erlang node.

Sending and Receiving Messages

The C node can receive a message from Erlang by calling
erl_receive msg(). This function reads data from the
open file descriptor fd into a buffer and puts the
result in an ErlMessage struct emsg.
ErlMessage has a field type defining what kind
of data is received. In this case, the type of interest is
ERL_REG_SEND which indicates that Erlang sent a message
to a registered process at the C node. The actual message, an
ETERM, is in the msg field.

It is also necessary to take care of the types
ERL_ERROR (an error occurred) and ERL_TICK
(alive check from other node, is to be ignored). Other
possible types indicate process events such as link, unlink,
and exit:

As the message is an ETERM struct, Erl_Interface
functions can be used to manipulate it. In this case, the
message becomes a 3-tuple, because that is how the Erlang code
is written. The second element will be the pid of the caller
and the third element will be the tuple {Function,Arg}
determining which function to call, and with which argument.
The result of calling the function is made into an
ETERM struct as well and sent back to Erlang using
erl_send(), which takes the open file descriptor, a
pid, and a term as arguments:

In Erlang/OTP R5B and later versions of OTP, the
include and lib directories are situated under
OTPROOT/lib/erl_interface-VSN, where OTPROOT is
the root directory of the OTP installation
(/usr/local/otp in the recent example) and VSN is
the version of the Erl_Interface application (3.2.1 in the
recent example).

In R4B and earlier versions of OTP, include and
lib are situated under OTPROOT/usr.

Step 2. Compile the Erlang code:

unix> erl -compile complex3 complex4

Step 3. Run the C node server example with short node names.

Do as follows:

Start the C program cserver and Erlang in
different windows.

cserver takes a port number as argument and must
be started before trying to call the Erlang functions.

The Erlang node is to be given the short name e1
and must be set to use the same magic cookie as the C node,
secretcookie: