From 2d3ab68c60e8bacf9e0efe403895e7065ef683be Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 12 Mar 2015 15:35:13 +0100 Subject: Update Interoperability Tutorial Language cleaned up by the technical writers xsipewe and tmanevik from Combitech. Proofreading and corrections by Hans Bolinder. --- system/doc/tutorial/c_port.xmlsrc | 86 ++++++++--- system/doc/tutorial/c_portdriver.xmlsrc | 112 +++++++-------- system/doc/tutorial/cnode.xmlsrc | 162 ++++++++++++++++----- system/doc/tutorial/erl_interface.xmlsrc | 108 ++++++++++---- system/doc/tutorial/example.xmlsrc | 21 ++- system/doc/tutorial/introduction.xml | 26 +++- system/doc/tutorial/nif.xmlsrc | 127 +++++++++-------- system/doc/tutorial/overview.xml | 235 +++++++++++++++++++++++++------ 8 files changed, 623 insertions(+), 254 deletions(-) diff --git a/system/doc/tutorial/c_port.xmlsrc b/system/doc/tutorial/c_port.xmlsrc index 8579da8520..0631293237 100644 --- a/system/doc/tutorial/c_port.xmlsrc +++ b/system/doc/tutorial/c_port.xmlsrc @@ -4,7 +4,7 @@
- 20002013 + 20002015 Ericsson AB. All Rights Reserved. @@ -28,16 +28,34 @@ c_port.xml
-

This is an example of how to solve the example problem by using a port.

+

This section outlines an example of how to solve the example + problem in the previous section + by using a port.

+

The scenario is illustrated in the following figure:

- Port Communication. + Port Communication
Erlang Program -

First of all communication between Erlang and C must be established by creating the port. The Erlang process which creates a port is said to be the connected process of the port. All communication to and from the port should go via the connected process. If the connected process terminates, so will the port (and the external program, if it is written correctly).

-

The port is created using the BIF open_port/2 with {spawn,ExtPrg} as the first argument. The string ExtPrg is the name of the external program, including any command line arguments. The second argument is a list of options, in this case only {packet,2}. This option says that a two byte length indicator will be used to simplify the communication between C and Erlang. Adding the length indicator will be done automatically by the Erlang port, but must be done explicitly in the external C program.

-

The process is also set to trap exits which makes it possible to detect if the external program fails.

+

All communication between Erlang and C must be established by + creating the port. The Erlang process that creates a port is + said to be the connected process of the port. All + communication to and from the port must go through the connected + process. If the connected process terminates, the port also + terminates (and the external program, if it is written + properly).

+

The port is created using the BIF open_port/2 with + {spawn,ExtPrg} as the first argument. The string + ExtPrg is the name of the external program, including any + command line arguments. The second argument is a list of + options, in this case only {packet,2}. This option says + that a 2 byte length indicator is to be used to simplify the + communication between C and Erlang. The Erlang port + automatically adds the length indicator, but this must be done + explicitly in the external C program.

+

The process is also set to trap exits, which enables detection + of failure of the external program:

 -module(complex1).
 -export([start/1, init/1]).
@@ -50,7 +68,9 @@ init(ExtPrg) ->
   process_flag(trap_exit, true),
   Port = open_port({spawn, ExtPrg}, [{packet, 2}]),
   loop(Port).
-

Now it is possible to implement complex1:foo/1 and complex1:bar/1. They both send a message to the complex process and receive the reply.

+

Now complex1:foo/1 and complex1:bar/1 can be + implemented. Both send a message to the complex process + and receive the following replies:

 foo(X) ->
   call_port({foo, X}).
@@ -63,7 +83,14 @@ call_port(Msg) ->
     {complex, Result} ->
       Result
   end.
-

The complex process encodes the message into a sequence of bytes, sends it to the port, waits for a reply, decodes the reply and sends it back to the caller.

+

The complex process does the following:

+ + Encodes the message into a sequence of bytes. + Sends it to the port. + Waits for a reply. + Decodes the reply. + Sends it back to the caller: +
 loop(Port) ->
   receive
@@ -75,37 +102,52 @@ loop(Port) ->
       end,
       loop(Port)
  end.
-

Assuming that both the arguments and the results from the C functions will be less than 256, a very simple encoding/decoding scheme is employed where foo is represented by the byte 1, bar is represented by 2, and the argument/result is represented by a single byte as well.

+

Assuming that both the arguments and the results from the C + functions are less than 256, a simple encoding/decoding scheme + is employed. In this scheme, foo is represented by byte + 1, bar is represented by 2, and the argument/result is + represented by a single byte as well:

 encode({foo, X}) -> [1, X];
 encode({bar, Y}) -> [2, Y].
-      
+
 decode([Int]) -> Int.
-

The resulting Erlang program, including functionality for stopping the port and detecting port failures is shown below. +

The resulting Erlang program, including functionality for + stopping the port and detecting port failures, is as follows:

C Program -

On the C side, it is necessary to write functions for receiving and sending - data with two byte length indicators from/to Erlang. By default, the C program - should read from standard input (file descriptor 0) and write to standard output - (file descriptor 1). Examples of such functions, read_cmd/1 and - write_cmd/2, are shown below.

+

On the C side, it is necessary to write functions for receiving + and sending data with 2 byte length indicators from/to Erlang. + By default, the C program is to read from standard input (file + descriptor 0) and write to standard output (file descriptor 1). + Examples of such functions, read_cmd/1 and + write_cmd/2, follows:

-

Note that stdin and stdout are for buffered input/output and should not be used for the communication with Erlang!

-

In the main function, the C program should listen for a message from Erlang and, according to the selected encoding/decoding scheme, use the first byte to determine which function to call and the second byte as argument to the function. The result of calling the function should then be sent back to Erlang.

+

Notice that stdin and stdout are for buffered + input/output and must not be used for the communication + with Erlang.

+

In the main function, the C program is to listen for a + message from Erlang and, according to the selected + encoding/decoding scheme, use the first byte to determine which + function to call and the second byte as argument to the + function. The result of calling the function is then to be sent + back to Erlang:

-

Note that the C program is in a while-loop checking for the return value of read_cmd/1. The reason for this is that the C program must detect when the port gets closed and terminate.

+

Notice that the C program is in a while-loop, checking + for the return value of read_cmd/1. This is because the C + program must detect when the port closes and terminates.

Running the Example -

1. Compile the C code.

+

Step 1. Compile the C code:

 unix> gcc -o extprg complex.c erl_comm.c port.c
-

2. Start Erlang and compile the Erlang code.

+

Step 2. Start Erlang and compile the Erlang code:

 unix> erl
 Erlang (BEAM) emulator version 4.9.1.2
@@ -113,7 +155,7 @@ Erlang (BEAM) emulator version 4.9.1.2
 Eshell V4.9.1.2 (abort with ^G)
 1> c(complex1).
 {ok,complex1}
-

3. Run the example.

+

Step 3. Run the example:

 2> complex1:start("extprg").
 <0.34.0>
diff --git a/system/doc/tutorial/c_portdriver.xmlsrc b/system/doc/tutorial/c_portdriver.xmlsrc
index 2fd6fb0aac..61187703a4 100644
--- a/system/doc/tutorial/c_portdriver.xmlsrc
+++ b/system/doc/tutorial/c_portdriver.xmlsrc
@@ -4,7 +4,7 @@
 
   
- 20002013 + 20002015 Ericsson AB. All Rights Reserved. @@ -21,46 +21,45 @@ - Port drivers + Port Drivers c_portdriver.xml
-

This is an example of how to solve the example problem by using a linked in port driver.

+

This section outlines an example of how to solve the example problem + in Problem Example + by using a linked-in port driver.

+

A port driver is a linked-in driver that is accessible as a port + from an Erlang program. It is a shared library (SO in UNIX, DLL in + Windows), with special entry points. The Erlang runtime system + calls these entry points when the driver is started and when data + is sent to the port. The port driver can also send data to + Erlang.

+

As a port driver is dynamically linked into the emulator process, + this is the fastest way of calling C-code from Erlang. Calling + functions in the port driver requires no context switches. But it + is also the least safe way, because a crash in the port driver + brings the emulator down too.

+

The scenario is illustrated in the following figure:

- Port Driver Communication. + Port Driver Communication -
- Port Drivers -

A port driver is a linked in driver that is accessible as a - port from an Erlang program. It is a shared library (SO in Unix, - DLL in Windows), with special entry points. The Erlang runtime - calls these entry points, when the driver is started and when - data is sent to the port. The port driver can also send data to - Erlang.

-

Since a port driver is dynamically linked into the emulator - process, this is the fastest way of calling C-code from Erlang. - Calling functions in the port driver requires no context - switches. But it is also the least safe, because a crash in the - port driver brings the emulator down too.

-
-
Erlang Program -

Just as with a port program, the port communicates with a Erlang +

Like a port program, the port communicates with an Erlang process. All communication goes through one Erlang process that is the connected process of the port driver. Terminating this process closes the port driver.

Before the port is created, the driver must be loaded. This is done with the function erl_dll:load_driver/1, with the name of the shared library as argument.

-

The port is then created using the BIF open_port/2 with +

The port is then created using the BIF open_port/2, with the tuple {spawn, DriverName} as the first argument. The string SharedLib is the name of the port driver. The second - argument is a list of options, none in this case.

+ argument is a list of options, none in this case:

 -module(complex5).
 -export([start/1, init/1]).
@@ -77,9 +76,9 @@ init(SharedLib) ->
   register(complex, self()),
   Port = open_port({spawn, SharedLib}, []),
   loop(Port).
-

Now it is possible to implement complex5:foo/1 and - complex5:bar/1. They both send a message to the - complex process and receive the reply.

+

Now complex5:foo/1 and complex5:bar/1 + can be implemented. Both send a message to the + complex process and receive the following reply:

 foo(X) ->
     call_port({foo, X}).
@@ -92,10 +91,14 @@ call_port(Msg) ->
         {complex, Result} ->
             Result
     end.
-

The complex process encodes the message into a sequence - of bytes, sends it to the port, waits for a reply, decodes the - reply and sends it back to the caller. -

+

The complex process performs the following:

+ + Encodes the message into a sequence of bytes. + Sends it to the port. + Waits for a reply. + Decodes the reply. + Sends it back to the caller: +
 loop(Port) ->
     receive
@@ -108,59 +111,58 @@ loop(Port) ->
             loop(Port)
     end.

Assuming that both the arguments and the results from the C - functions will be less than 256, a very simple encoding/decoding - scheme is employed where foo is represented by the byte + functions are less than 256, a simple encoding/decoding scheme + is employed. In this scheme, foo is represented by byte 1, bar is represented by 2, and the argument/result is - represented by a single byte as well. -

+ represented by a single byte as well:

 encode({foo, X}) -> [1, X];
 encode({bar, Y}) -> [2, Y].
-      
+
 decode([Int]) -> Int.
-

The resulting Erlang program, including functionality for - stopping the port and detecting port failures is shown below.

+

The resulting Erlang program, including functions for stopping + the port and detecting port failures, is as follows:

C Driver

The C driver is a module that is compiled and linked into a - shared library. It uses a driver structure, and includes the + shared library. It uses a driver structure and includes the header file erl_driver.h.

The driver structure is filled with the driver name and function pointers. It is returned from the special entry point, declared with the macro )]]>.

-

The functions for receiving and sending data, are combined into +

The functions for receiving and sending data are combined into a function, pointed out by the driver structure. The data sent - into the port is given as arguments, and the data the port - sends back is sent with the C-function driver_output.

-

Since the driver is a shared module, not a program, no main - function should be present. All function pointers are not used - in our example, and the corresponding fields in the + into the port is given as arguments, and the replied data is sent + with the C-function driver_output.

+

As the driver is a shared module, not a program, no main + function is present. All function pointers are not used + in this example, and the corresponding fields in the driver_entry structure are set to NULL.

-

All functions in the driver, takes a handle (returned from - start), that is just passed along by the erlang +

All functions in the driver takes a handle (returned from + start) that is just passed along by the Erlang process. This must in some way refer to the port driver instance.

-

The example_drv_start, is the only function that is called with - a handle to the port instance, so we must save this. It is - customary to use a allocated driver-defined structure for this - one, and pass a pointer back as a reference.

-

It is not a good idea to use a global variable; since the port - driver can be spawned by multiple Erlang processes, this - driver-structure should be instantiated multiple times. +

The example_drv_start, is the only function that is called with + a handle to the port instance, so this must be saved. It is + customary to use an allocated driver-defined structure for this + one, and to pass a pointer back as a reference.

+

It is not a good idea to use a global variable as the port + driver can be spawned by multiple Erlang processes. This + driver-structure is to be instantiated multiple times:

Running the Example -

1. Compile the C code.

+

Step 1. Compile the C code:

 unix> gcc -o exampledrv -fpic -shared complex.c port_driver.c
 windows> cl -LD -MD -Fe exampledrv.dll complex.c port_driver.c
-

2. Start Erlang and compile the Erlang code.

+

Step 2. Start Erlang and compile the Erlang code:

 > erl
 Erlang (BEAM) emulator version 5.1
@@ -168,7 +170,7 @@ Erlang (BEAM) emulator version 5.1
 Eshell V5.1 (abort with ^G)
 1> c(complex5).
 {ok,complex5}
-

3. Run the example.

+

Step 3. Run the example:

 2> complex5:start("example_drv").
 <0.34.0>
diff --git a/system/doc/tutorial/cnode.xmlsrc b/system/doc/tutorial/cnode.xmlsrc
index 293406160f..bcdd1298de 100644
--- a/system/doc/tutorial/cnode.xmlsrc
+++ b/system/doc/tutorial/cnode.xmlsrc
@@ -4,7 +4,7 @@
 
   
- 20002013 + 20002015 Ericsson AB. All Rights Reserved. @@ -28,19 +28,39 @@ cnode.xml
-

This is an example of how to solve the example problem by using a C node. Note that a C node would not typically be used for solving a simple problem like this, a port would suffice.

+

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.

Erlang Program -

From Erlang's point of view, the C node is treated like a normal Erlang node. Therefore, 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; a process which 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.

+

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 should be the name of the C node. If short node names are used, the plain name of the node will be 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 could be any atom. The name can be ignored by the C code, or it could be used for example to distinguish between different types of messages. Below is an example of what the Erlang code could look like when using short node names. +

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:

- When using long node names the code is slightly different as shown in the following example: + When using long node names, the code is slightly different as + shown in the following example:

@@ -50,39 +70,77 @@ C Program
- Setting Up the Communication -

Before calling any other Erl_Interface function, the memory handling must be initiated.

+ Setting Up Communication +

Before calling any other function in Erl_Interface, the + memory handling must be initiated:

 erl_init(NULL, 0);
-

Now the C node can be initiated. If short node names are used, this is done by calling erl_connect_init().

+

Now the C node can be initiated. If short node names are + used, this is done by calling erl_connect_init():

 erl_connect_init(1, "secretcookie", 0);
-

The first argument is the integer which is used to construct the node name. In the example the plain node name will be c1.

- - The second argument is a string defining the magic cookie.

- - The third argument is an integer which is used to identify a particular instance of a C node.

-

If long node node names are used, initiation is done by calling erl_connect_xinit().

+

Here:

+ + The first argument is the integer used to construct the node name. +

In the example, the plain node name is c1.

+ The second argument is a string defining the magic cookie. + The third argument is an integer that is used to identify + a particular instance of a C node. +
+

If long node node names are used, initiation is done by + calling erl_connect_xinit():

 erl_connect_xinit("idril", "cnode", "cnode@idril.ericsson.se",
                   &addr, "secretcookie", 0);
-

The first three arguments are the host name, the plain node name, and the full node name. The fourth argument is a pointer to an in_addr struct with the IP address of the host, and the fifth and sixth arguments are the magic cookie and instance number.

-

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

+

Here:

+ + The first argument is the host name. + The second argument is the plain node name. + The third argument is the full node name. + 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, see the man page for epmd).

+

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.

+

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 that will contain useful information when a connection has been established; for example, the name of the Erlang node.

+

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 which kind of data was 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, will be 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, should be ignored). Other possible types indicate process events such as link/unlink and exit.

+

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:

   while (loop) {
 
@@ -93,7 +151,16 @@ fd = erl_accept(listen, &conn);
loop = 0; /* exit while loop */ } else { if (emsg.type == ERL_REG_SEND) {
-

Since the message is an ETERM struct, Erl_Interface functions can be used to manipulate it. In this case, the message will be a 3-tuple (because that was how the Erlang code was written, see above). 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 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.

+

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:

         fromp = erl_element(2, emsg.msg);
         tuplep = erl_element(3, emsg.msg);
@@ -108,29 +175,30 @@ fd = erl_accept(listen, &conn);
resp = erl_format("{cnode, ~i}", res); erl_send(fd, fromp, resp);
-

Finally, the memory allocated by the ETERM creating functions (including erl_receive_msg() must be freed.

+

Finally, the memory allocated by the ETERM creating + functions (including erl_receive_msg() must be + freed:

         erl_free_term(emsg.from); erl_free_term(emsg.msg);
         erl_free_term(fromp); erl_free_term(tuplep);
         erl_free_term(fnp); erl_free_term(argp);
         erl_free_term(resp);
-

The resulting C programs can be found in looks like the following examples. First a C node server using short node names.

+

The following examples show the resulting C programs. + First a C node server using short node names:

-

Below follows a C node server using long node names.

+

A C node server using long node names:

-

And finally we have the code for the C node client.

+

Finally, the code for the C node client:

Running the Example -

1. Compile the C code, providing the paths to the Erl_Interface include files and libraries, and to the socket and nsl libraries.

-

In 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 example above) and VSN is the version of the erl_interface application (3.2.1 in the example above).

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

+

Step 1. Compile the C code. This provides the paths to + the Erl_Interface include files and libraries, and to the + socket and nsl libraries:

-      
 >  gcc -o cserver \\ 
 -I/usr/local/otp/lib/erl_interface-3.2.1/include \\ 
 -L/usr/local/otp/lib/erl_interface-3.2.1/lib \\ 
@@ -148,11 +216,29 @@ unix> gcc -o cclient \\ 
 -L/usr/local/otp/lib/erl_interface-3.2.1/lib \\ 
 complex.c cnode_c.c \\ 
 -lerl_interface -lei -lsocket -lnsl
-

2. Compile the Erlang code.

+

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
-

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

-

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 should be given the short name e1 and must be set to use the same magic cookie as the C node, secretcookie.

+

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: +
 unix> cserver 3456
 
@@ -164,7 +250,9 @@ Eshell V4.9.1.2  (abort with ^G)
 4
 (e1@idril)2> complex3:bar(5).
 10
-

4. Run the C node client example. Terminate cserver but not Erlang and start cclient. The Erlang node must be started before the C node client is.

+

Step 4. Run the C node client example. Terminate + cserver, but not Erlang, and start cclient. The + Erlang node must be started before the C node client:

 unix> cclient
 
@@ -172,7 +260,7 @@ unix> cclient
 4
 (e1@idril)4> complex3:bar(5).
 10
-

5. Run the C node server, long node names, example.

+

Step 5. Run the C node server example with long node names:

 unix> cserver2 3456
 
diff --git a/system/doc/tutorial/erl_interface.xmlsrc b/system/doc/tutorial/erl_interface.xmlsrc
index 0c4c5a99c2..5751a945d6 100644
--- a/system/doc/tutorial/erl_interface.xmlsrc
+++ b/system/doc/tutorial/erl_interface.xmlsrc
@@ -4,7 +4,7 @@
 
   
- 20002013 + 20002015 Ericsson AB. All Rights Reserved. @@ -28,14 +28,29 @@ erl_interface.xml
-

This is an example of how to solve the example problem by using a port and erl_interface. It is necessary to read the port example before reading this chapter.

+ +

This section outlines an example of how to solve the example + problem in Problem Example by + using a port and Erl_Interface. It is necessary to read the port + example in Ports before reading + this section.

Erlang Program -

The example below shows an Erlang program communicating with a C program over a plain port with home made encoding.

- -

Compared to the Erlang module - above used for the plain port, there are two differences when using Erl_Interface on the C side: Since Erl_Interface operates on the Erlang external term format the port must be set to use binaries and, instead of inventing an encoding/decoding scheme, the BIFs term_to_binary/1 and binary_to_term/1 should be used. That is:

+

The following example shows an Erlang program communicating + with a C program over a plain port with home made encoding:

+ +

There are two differences when using Erl_Interface on the C + side compared to the example in + Ports, using only the plain port:

+ + As Erl_Interface operates on the Erlang external term format, + the port must be set to use binaries. + Instead of inventing an encoding/decoding scheme, the + term_to_binary/1 and binary_to_term/1 BIFs are to + be used. + +

That is:

 open_port({spawn, ExtPrg}, [{packet, 2}])

is replaced with:

@@ -55,69 +70,110 @@ receive {Port, {data, Data}} -> Caller ! {complex, binary_to_term(Data)} end
-

The resulting Erlang program is shown below.

+

The resulting Erlang program is as follows:

-

Note that calling complex2:foo/1 and complex2:bar/1 will result in the tuple {foo,X} or {bar,Y} being sent to the complex process, which will code them as binaries and send them to the port. This means that the C program must be able to handle these two tuples.

+

Notice that calling complex2:foo/1 and + complex2:bar/1 results in the tuple {foo,X} or + {bar,Y} being sent to the complex process, which + codes them as binaries and sends them to the port. This means + that the C program must be able to handle these two tuples.

C Program -

The example below shows a C program communicating with an Erlang program over a plain port with home made encoding.

+

The following example shows a C program communicating with an + Erlang program over a plain port with home made encoding:

-

Compared to the C program above - used for the plain port the while-loop must be rewritten. Messages coming from the port will be on the Erlang external term format. They should be converted into an ETERM struct, a C struct similar to an Erlang term. The result of calling foo() or bar() must be converted to the Erlang external term format before being sent back to the port. But before calling any other erl_interface function, the memory handling must be initiated.

+

Compared to the C program in + Ports, using only the plain port, the + while-loop must be rewritten. Messages coming from the + port is on the Erlang external term format. They must be + converted into an ETERM struct, which is a C struct + similar to an Erlang term. The result of calling foo() or + bar() must be converted to the Erlang external term + format before being sent back to the port. But before calling + any other Erl_Interface function, the memory handling must be + initiated:

 erl_init(NULL, 0);
-

For reading from and writing to the port the functions read_cmd() and write_cmd() from the erl_comm.c example below - can still be used. +

The following functions, read_cmd() and + write_cmd(), from the erl_comm.c example in + Ports can still be + used for reading from and writing to the port:

-

The function erl_decode() from erl_marshal will convert the binary into an ETERM struct.

+

The function erl_decode() from erl_marshal + converts the binary into an ETERM struct:

 int main() {
   ETERM *tuplep;
 
   while (read_cmd(buf) > 0) {
     tuplep = erl_decode(buf);
-

In this case tuplep now points to an ETERM struct representing a tuple with two elements; the function name (atom) and the argument (integer). By using the function erl_element() from erl_eterm it is possible to extract these elements, which also must be declared as pointers to an ETERM struct.

+

Here, tuplep points to an ETERM struct + representing a tuple with two elements; the function name (atom) + and the argument (integer). Using the function + erl_element() from erl_eterm, these elements can + be extracted, but they must also be declared as pointers to an + ETERM struct:

     fnp = erl_element(1, tuplep);
     argp = erl_element(2, tuplep);
-

The macros ERL_ATOM_PTR and ERL_INT_VALUE from erl_eterm can be used to obtain the actual values of the atom and the integer. The atom value is represented as a string. By comparing this value with the strings "foo" and "bar" it can be decided which function to call.

+

The macros ERL_ATOM_PTR and ERL_INT_VALUE from + erl_eterm can be used to obtain the actual values of the + atom and the integer. The atom value is represented as a string. + By comparing this value with the strings "foo" and "bar", it can + be decided which function to call:

     if (strncmp(ERL_ATOM_PTR(fnp), "foo", 3) == 0) {
       res = foo(ERL_INT_VALUE(argp));
     } else if (strncmp(ERL_ATOM_PTR(fnp), "bar", 3) == 0) {
       res = bar(ERL_INT_VALUE(argp));
     }
-

Now an ETERM struct representing the integer result can be constructed using the function erl_mk_int() from erl_eterm. It is also possible to use the function erl_format() from the module erl_format.

+

Now an ETERM struct that represents the integer result + can be constructed using the function erl_mk_int() from + erl_eterm. The function + erl_format() from the module erl_format can also + be used:

     intp = erl_mk_int(res);
-

The resulting ETERM struct is converted into the Erlang external term format using the function erl_encode() from erl_marshal and sent to Erlang using write_cmd().

+

The resulting ETERM struct is converted into the Erlang + external term format using the function erl_encode() from + erl_marshal and sent to Erlang using + write_cmd():

     erl_encode(intp, buf);
     write_cmd(buf, erl_eterm_len(intp));
-

Last, the memory allocated by the ETERM creating functions must be freed.

+

Finally, the memory allocated by the ETERM creating + functions must be freed:

     erl_free_compound(tuplep);
     erl_free_term(fnp);
     erl_free_term(argp);
     erl_free_term(intp);
-

The resulting C program is shown below:

+

The resulting C program is as follows:

Running the Example -

1. Compile the C code, providing the paths to the include files erl_interface.h and ei.h, and to the libraries erl_interface and ei.

+

Step 1. Compile the C code. This provides the paths to + the include files erl_interface.h and ei.h, and + also to the libraries erl_interface and ei:

 unix> gcc -o extprg -I/usr/local/otp/lib/erl_interface-3.2.1/include \\ 
       -L/usr/local/otp/lib/erl_interface-3.2.1/lib \\ 
       complex.c erl_comm.c ei.c -lerl_interface -lei
-

In 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 example above) and VSN is the version of the erl_interface application (3.2.1 in the example above).

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

-

2. Start Erlang and compile the Erlang code.

+

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. Start Erlang and compile the Erlang code:

 unix> erl
 Erlang (BEAM) emulator version 4.9.1.2
@@ -125,7 +181,7 @@ Erlang (BEAM) emulator version 4.9.1.2
 Eshell V4.9.1.2 (abort with ^G)
 1> c(complex2).
 {ok,complex2}
-

3. Run the example.

+

Step 3. Run the example:

 2> complex2:start("extprg").
 <0.34.0>
diff --git a/system/doc/tutorial/example.xmlsrc b/system/doc/tutorial/example.xmlsrc
index f87eb217e9..e205ca189e 100644
--- a/system/doc/tutorial/example.xmlsrc
+++ b/system/doc/tutorial/example.xmlsrc
@@ -4,7 +4,7 @@
 
   
- 20002013 + 20002015 Ericsson AB. All Rights Reserved. @@ -31,16 +31,25 @@
Description -

A common interoperability situation is when there exists a piece of code solving some complex problem, and we would like to incorporate this piece of code in our Erlang program. Suppose for example we have the following C functions that we would like to be able to call from Erlang.

- -

(For the sake of keeping the example as simple as possible, the functions are not very complicated in this case).

-

Preferably we would like to able to call foo and bar without having to bother about them actually being C functions.

+

A common interoperability situation is when you want to incorporate + a piece of code, solving a complex problem, in your Erlang + program. Suppose for example, that you have the following C + functions that you would like to call from Erlang:

+ +

The functions are deliberately kept as simple as possible, for + readability reasons.

+

From an Erlang perspektive, it is preferable to be able to call + foo and bar without having to bother about that + they are C functions:

 % Erlang code
 ...
 Res = complex:foo(X),
 ...
-

The communication with C is hidden in the implementation of complex.erl. In the following chapters it is shown how this module can be implemented using the different interoperability mechanisms.

+

Here, the communication with C is hidden in the implementation + of complex.erl. + In the following sections, it is shown how this module can be + implemented using the different interoperability mechanisms.

diff --git a/system/doc/tutorial/introduction.xml b/system/doc/tutorial/introduction.xml index ed86a00f76..dcf462e311 100644 --- a/system/doc/tutorial/introduction.xml +++ b/system/doc/tutorial/introduction.xml @@ -4,7 +4,7 @@
- 20002013 + 20002015 Ericsson AB. All Rights Reserved. @@ -28,18 +28,34 @@ introduction.xml
+ +

This section informs on interoperability, that is, information + exchange, between Erlang and other programming languages. The + included examples mainly treat interoperability between Erlang and + C.

Purpose -

The purpose of this tutorial is to give the reader an orientation of the different interoperability mechanisms that can be used when integrating a program written in Erlang with a program written in another programming language, from the Erlang programmer's point of view.

+

The purpose of this tutorial is to describe different + interoperability mechanisms that can be used when integrating a + program written in Erlang with a program written in another + programming language, from the Erlang programmer's + perspective.

Prerequisites -

It is assumed that the reader is a skilled Erlang programmer, familiar with concepts such as Erlang data types, processes, messages and error handling.

-

To illustrate the interoperability principles C programs running in a UNIX environment have been used. It is assumed that the reader has enough knowledge to be able to apply these principles to the relevant programming languages and platforms.

+

It is assumed that you are a skilled Erlang programmer, + familiar with concepts such as Erlang data types, processes, + messages, and error handling.

+

To illustrate the interoperability principles, C programs + running in a UNIX environment have been used. It is assumed that + you have enough knowledge to apply these principles to the + relevant programming languages and platforms.

-

For the sake of readability, the example code has been kept as simple as possible. It does not include functionality such as error handling, which might be vital in a real-life system.

+

For readability, the example code is kept as simple as + possible. For example, it does not include error handling, + which might be vital in a real-life system.

diff --git a/system/doc/tutorial/nif.xmlsrc b/system/doc/tutorial/nif.xmlsrc index 8ddad60f74..c79370e8c8 100644 --- a/system/doc/tutorial/nif.xmlsrc +++ b/system/doc/tutorial/nif.xmlsrc @@ -4,7 +4,7 @@
- 20002013 + 20002015 Ericsson AB. All Rights Reserved. @@ -28,92 +28,105 @@ nif.xml
-

This is an example of how to solve the example problem - by using NIFs. NIFs were introduced in R13B03 as an experimental - feature. It is a simpler and more efficient way of calling C-code - than using port drivers. NIFs are most suitable for synchronous functions like - foo and bar in the example, that does some - relatively short calculations without side effects and return the result.

-
- NIFs -

A NIF (Native Implemented Function) is a function that is - implemented in C instead of Erlang. NIFs appear as any other functions to - the callers. They belong to a module and are called like any other Erlang - functions. The NIFs of a module are compiled and linked into a dynamic - loadable shared library (SO in Unix, DLL in Windows). The NIF library must - be loaded in runtime by the Erlang code of the module.

-

Since a NIF library is dynamically linked into the emulator - process, this is the fastest way of calling C-code from Erlang (alongside - port drivers). Calling NIFs requires no context switches. But it is also - the least safe, because a crash in a NIF will bring the emulator down - too.

-
+

This section outlines an example of how to solve the example + problem in Problem Example + by using Native Implemented Functions (NIFs).

+

NIFs were introduced in Erlang/OTP R13B03 as an experimental + feature. It is a simpler and more efficient way of calling C-code + than using port drivers. NIFs are most suitable for synchronous + functions, such as foo and bar in the example, that + do some relatively short calculations without side effects and + return the result.

+

A NIF is a function that is implemented in C instead of Erlang. + NIFs appear as any other functions to the callers. They belong to + a module and are called like any other Erlang functions. The NIFs + of a module are compiled and linked into a dynamic loadable, + shared library (SO in UNIX, DLL in Windows). The NIF library must + be loaded in runtime by the Erlang code of the module.

+

As a NIF library is dynamically linked into the emulator process, + this is the fastest way of calling C-code from Erlang (alongside + port drivers). Calling NIFs requires no context switches. But it + is also the least safe, because a crash in a NIF brings the + emulator down too.

Erlang Program -

Even if all functions of a module will be NIFs, you still need an Erlang - module for two reasons. First, the NIF library must be explicitly loaded - by Erlang code in the same module. Second, all NIFs of a module must have - an Erlang implementation as well. Normally these are minimal stub - implementations that throw an exception. But it can also be used as - fallback implementations for functions that do not have native - implemenations on some architectures.

-

NIF libraries are loaded by calling erlang:load_nif/2, with the - name of the shared library as argument. The second argument can be any - term that will be passed on to the library and used for - initialization.

+

Even if all functions of a module are NIFs, an Erlang + module is still needed for two reasons:

+ + The NIF library must be explicitly loaded by + Erlang code in the same module. + All NIFs of a module must have an Erlang implementation + as well. + +

Normally these are minimal stub implementations that throw an + exception. But they can also be used as fallback implementations + for functions that do not have native implemenations on some + architectures.

+

NIF libraries are loaded by calling erlang:load_nif/2, + with the name of the shared library as argument. The second + argument can be any term that will be passed on to the library + and used for initialization:

-

We use the directive on_load to get function init to be - automatically called when the module is loaded. If init - returns anything other than ok, such when the loading of - the NIF library fails in this example, the module will be - unloaded and calls to functions within it will fail.

-

Loading the NIF library will override the stub implementations +

Here, the directive on_load is used to get function + init to be automatically called when the module is + loaded. If init returns anything other than ok, + such when the loading of the NIF library fails in this example, + the module is unloaded and calls to functions within it, + fail.

+

Loading the NIF library overrides the stub implementations and cause calls to foo and bar to be dispatched to the NIF implementations instead.

- NIF library code + NIF Library Code

The NIFs of the module are compiled and linked into a shared library. Each NIF is implemented as a normal C function. The macro ERL_NIF_INIT together with an array of structures defines the names, - arity and function pointers of all the NIFs in the module. The header - file erl_nif.h must be included. Since the library is a shared - module, not a program, no main function should be present.

+ arity, and function pointers of all the NIFs in the module. The header + file erl_nif.h must be included. As the library is a shared + module, not a program, no main function is to be present.

The function arguments passed to a NIF appears in an array argv, - with argc as the length of the array and thus the arity of the + with argc as the length of the array, and thus the arity of the function. The Nth argument of the function can be accessed as argv[N-1]. NIFs also take an environment argument that serves as an opaque handle that is needed to be passed on to most API functions. The environment contains information about - the calling Erlang process.

+ the calling Erlang process:

-

The first argument to ERL_NIF_INIT must be the name of the +

Here,ERL_NIF_INIT has the following arguments:

+ +

The first argument must be the name of the Erlang module as a C-identifier. It will be stringified by the - macro. The second argument is the array of ErlNifFunc - structures containing name, arity and function pointer of - each NIF. The other arguments are pointers to callback functions - that can be used to initialize the library. We do not use them - in this simple example so we set them all to NULL.

+ macro.

+
+ The second argument is the array of ErlNifFunc + structures containing name, arity, and function pointer of + each NIF. + The remaining arguments are pointers to callback functions + that can be used to initialize the library. They are not used + in this simple example, hence they are all set to NULL. +

Function arguments and return values are represented as values - of type ERL_NIF_TERM. We use functions like enif_get_int - and enif_make_int to convert between Erlang term and C-type. - If the function argument argv[0] is not an integer then - enif_get_int will return false, in which case we return + of type ERL_NIF_TERM. Here, functions like enif_get_int + and enif_make_int are used to convert between Erlang term + and C-type. + If the function argument argv[0] is not an integer, + enif_get_int returns false, in which case it returns by throwing a badarg-exception with enif_make_badarg.

Running the Example -

1. Compile the C code.

+

Step 1. Compile the C code:

 unix> gcc -o complex6_nif.so -fpic -shared complex.c complex6_nif.c
 windows> cl -LD -MD -Fe complex6_nif.dll complex.c complex6_nif.c
-

2. Start Erlang and compile the Erlang code.

+

Step 2: Start Erlang and compile the Erlang code:

 > erl
 Erlang R13B04 (erts-5.7.5) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]
@@ -121,7 +134,7 @@ Erlang R13B04 (erts-5.7.5) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-p
 Eshell V5.7.5  (abort with ^G)
 1> c(complex6).
 {ok,complex6}
-

3. Run the example.

+

Step 3: Run the example:

 3> complex6:foo(3).
 4
diff --git a/system/doc/tutorial/overview.xml b/system/doc/tutorial/overview.xml
index 1fe1aad22b..3814a135b4 100644
--- a/system/doc/tutorial/overview.xml
+++ b/system/doc/tutorial/overview.xml
@@ -4,7 +4,7 @@
 
   
- 20002013 + 20002015 Ericsson AB. All Rights Reserved. @@ -31,35 +31,90 @@
Built-In Mechanisms -

There are two interoperability mechanisms built into the Erlang runtime system. One is distributed Erlang and the other one is ports. A variation of ports is linked-in drivers.

+

Two interoperability mechanisms are built into the Erlang + runtime system, distributed Erlang and ports. + A variation of ports is linked-in drivers.

Distributed Erlang -

An Erlang runtime system is made into a distributed Erlang node by giving it a name. A distributed Erlang node can connect to and monitor other nodes, it is also possible to spawn processes at other nodes. Message passing and error handling between processes at different nodes are transparent. There exists a number of useful stdlib modules intended for use in a distributed Erlang system; for example, global which provides global name registration. The distribution mechanism is implemented using TCP/IP sockets.

-

When to use: Distributed Erlang is primarily used for communication Erlang-Erlang. It can also be used for communication between Erlang and C, if the C program is implemented as a C node, see below.

-

Where to read more: Distributed Erlang and some distributed programming techniques are described in the Erlang book.

- - In the Erlang/OTP documentation there is a chapter about distributed Erlang in "Getting Started" (User's Guide).

- - Relevant man pages are erlang (describes the BIFs) and global, net_adm, pg2, rpc, pool and slave.

+

An Erlang runtime system is made a distributed Erlang node by + giving it a name. A distributed Erlang node can connect to, + and monitor, other nodes. It can also spawn processes at other + nodes. Message passing and error handling between processes at + different nodes are transparent. A number of useful STDLIB + modules are available in a distributed Erlang system. For + example, global, which provides global name + registration. The distribution mechanism is implemented using + TCP/IP sockets.

+

When to use: Distributed Erlang is primarily used + for Erlang-Erlang communication. It can also be used for + communication between Erlang and C, if the C program is + implemented as a C node, see + C and Java Libraries.

+

Where to read more: Distributed Erlang and some distributed + programming techniques are described in the Erlang book.

+

For more information, see + Distributed Programming.

+

Relevant manual pages are the following:

+ + erlang manual page in ERTS + (describes the BIFs) + global manual page in Kernel + net_adm manual page in Kernel + pg2 manual page in Kernel + rpc manual page in Kernel + pool manual page in STDLIB + slave manual page in STDLIB +
Ports and Linked-In Drivers -

Ports provide the basic mechanism for communication with the external world, from Erlang's point of view. They provide a byte-oriented interface to an external program. When a port has been created, Erlang can communicate with it by sending and receiving lists of bytes (not Erlang terms). This means that the programmer may have to invent a suitable encoding and decoding scheme.

-

The actual implementation of the port mechanism depends on the platform. In the Unix case, pipes are used and the external program should as default read from standard input and write to standard output. Theoretically, the external program could be written in any programming language as long as it can handle the interprocess communication mechanism with which the port is implemented.

-

The external program resides in another OS process than the Erlang runtime system. In some cases this is not acceptable, consider for example drivers with very hard time requirements. It is therefore possible to write a program in C according to certain principles and dynamically link it to the Erlang runtime system, this is called a linked-in driver.

-

When to use: Being the basic mechanism, ports can be used for all kinds of interoperability situations where the Erlang program and the other program runs on the same machine. Programming is fairly straight-forward.

- - Linked-in drivers involves writing certain call-back functions in C. Very good skills are required as the code is linked to the Erlang runtime system.

+

Ports provide the basic mechanism for communication with the + external world, from Erlang's point of view. The ports provide + a byte-oriented interface to an external program. When a port + is created, Erlang can communicate with it by sending and + receiving lists of bytes (not Erlang terms). This means that + the programmer might have to invent a suitable encoding and + decoding scheme.

+

The implementation of the port mechanism depends on the + platform. For UNIX, pipes are used and the external program is + assumed to read from standard input and write to standard + output. The external program can be written in any programming + language as long as it can handle the interprocess + communication mechanism with which the port is + implemented.

+

The external program resides in another OS process than the + Erlang runtime system. In some cases this is not acceptable. + Consider, for example, drivers with very hard time + requirements. It is therefore possible to write a program in C + according to certain principles, and dynamically link it to + the Erlang runtime system. This is called a linked-in + driver.

+

When to use: Ports can be used for all kinds of + interoperability situations where the Erlang program and the + other program runs on the same machine. Programming is fairly + straight-forward.

+

Linked-in drivers involves writing certain call-back + functions in C. This requires very good skills as the code is + linked to the Erlang runtime system.

-

An erroneous linked-in driver will cause the entire Erlang runtime system to leak memory, hang or crash.

+

A faulty linked-in driver causes the entire Erlang runtime + system to leak memory, hang, or crash.

-

Where to read more: Ports are described in the "Miscellaneous Items" chapter of the Erlang book. Linked-in drivers are described in Appendix E.

- - The BIF open_port/2 is documented in the man page for erlang. For linked-in drivers, the programmer needs to read the information in the man page for erl_ddll.

-

Examples:Port example.

+

Where to read more: Ports are described in section + "Miscellaneous Items" of the Erlang book. Linked-in drivers + are described in Appendix E.

+

The BIF open_port/2 is documented in the + erlang manual page in + ERTS.

+

For linked-in drivers, the programmer needs to read the + erl_ddll manual + page in Kernel.

+

Examples: Port example in + Ports.

@@ -68,64 +123,152 @@
Erl_Interface -

Very often the program at the other side of a port is a C program. To help the C programmer a library called Erl_Interface has been developed. It consists of five parts:

+

The program at the other side of a port is often a C program. + To help the C programmer, the Erl_Interface library + has been developed, including the following five parts:

- erl_marshal, erl_eterm, erl_format, erl_malloc Handling of the Erlang external term format. - erl_connect Communication with distributed Erlang, see C nodes below. - erl_error Error print routines. - erl_global Access globally registered names. - Registry Store and backup of key-value pairs. + + erl_marshal, erl_eterm, erl_format, and + erl_malloc: Handling of the Erlang external term format + + erl_connect: + Communication with distributed Erlang, see C nodes below + + erl_error: + Error print routines + + erl_global: + Access globally registered names + + Registry: + Store and backup of key-value pairs -

The Erlang external term format is a representation of an Erlang term as a sequence of bytes, a binary. Conversion between the two representations is done using BIFs.

+

The Erlang external term format is a representation of an + Erlang term as a sequence of bytes, that is, a binary. + Conversion between the two representations is done using the + following BIFs:

 Binary = term_to_binary(Term)
 Term = binary_to_term(Binary)
-

A port can be set to use binaries instead of lists of bytes. It is then not necessary to invent any encoding/decoding scheme. Erl_Interface functions are used for unpacking the binary and convert it into a struct similar to an Erlang term. Such a struct can be manipulated in different ways and be converted to the Erlang external format and sent to Erlang.

+

A port can be set to use binaries instead of lists of bytes. + It is then not necessary to invent any encoding/decoding + scheme. Erl_Interface functions are used for unpacking the + binary and convert it into a struct similar to an Erlang term. + Such a struct can be manipulated in different ways, be + converted to the Erlang external format, and sent to + Erlang.

When to use: In C code, in conjunction with Erlang binaries.

-

Where to read more: Read about the Erl_Interface User's Guide; Command Reference and Library Reference. In R5B and earlier versions the information can be found under the Kernel application.

-
-

Examples:erl_interface example.

+

Where to read more: See the Erlang Interface User's + Guide, Command Reference, and Library Reference. In Erlang/OTP + R5B, and earlier versions, the information is part of the + Kernel application.

+

Examples: Erl_Interface example in + Erl_Interface.

C Nodes -

A C program which uses the Erl_Interface functions for setting up a connection to and communicating with a distributed Erlang node is called a C node, or a hidden node. The main advantage with a C node is that the communication from the Erlang programmer's point of view is extremely easy, since the C program behaves as a distributed Erlang node.

-

When to use: C nodes can typically be used on device processors (as opposed to control processors) where C is a better choice than Erlang due to memory limitations and/or application characteristics.

-

Where to read more: In the erl_connect part of the Erl_Interface documentation, see above. The programmer also needs to be familiar with TCP/IP sockets, see below, and distributed Erlang, see above.

-

Examples:C node example.

+

A C program that uses the Erl_Interface functions for setting + up a connection to, and communicating with, a distributed + Erlang node is called a C node, or a hidden + node. The main advantage with a C node is that the + communication from the Erlang programmer's perspective is + extremely easy, as the C program behaves as a distributed + Erlang node.

+

When to use: C nodes can typically be used on device + processors (as opposed to control processors) where C is a + better choice than Erlang due to memory limitations or + application characteristics, or both.

+

Where to read more: See the erl_connect part + of the Erl_Interface documentation. The programmer also needs + to be familiar with TCP/IP sockets, see Sockets in Standard + Protocols and Distributed Erlang in Built-In Mechanisms.

+

Example: C node example in + C Nodes.

Jinterface -

In Erlang/OTP R6B, a library similar to Erl_Interface for Java was added called jinterface.

+

In Erlang/OTP R6B, a library similar to Erl_Interface for + Java was added called jinterface. It provides a tool + for Java programs to communicate with Erlang nodes.

Standard Protocols -

Sometimes communication between an Erlang program and another program using a standard protocol is desirable. Erlang/OTP currently supports TCP/IP and UDP sockets, SNMP, HTTP and IIOP (CORBA). Using one of the latter three requires good knowledge about the protocol and is not covered by this tutorial. Please refer to the documentation for the SNMP, Inets and Orber applications, respectively.

+

Sometimes communication between an Erlang program and another + program using a standard protocol is desirable. Erlang/OTP + currently supports TCP/IP and UDP sockets: as + follows:

+ + SNMP + HTTP + IIOP (CORBA) + +

Using one of the latter three requires good knowledge about the + protocol and is not covered by this tutorial. See the SNMP, + Inets, and Orber applications, respectively.

Sockets -

Simply put, connection-oriented socket communication (TCP/IP) consists of an initiator socket ("server") started at a certain host with a certain port number. A connector socket ("client") aware of the initiator's host name and port number can connect to it and data can be sent between them. Connection-less socket communication (UDP) consists of an initiator socket at a certain host with a certain port number and a connector socket sending data to it. For a detailed description of the socket concept, please refer to a suitable book about network programming. A suggestion is UNIX Network Programming, Volume 1: Networking APIs - Sockets and XTI by W. Richard Stevens, ISBN: 013490012X.

-

In Erlang/OTP, access to TCP/IP and UDP sockets is provided by the - Kernel modules gen_tcp and gen_udp. Both are easy to - use and do not require any deeper knowledge about the socket concept.

-

When to use: For programs running on the same or on another machine than the Erlang program.

-

Where to read more: The man pages for gen_tcp and gen_udp.

+

Simply put, connection-oriented socket communication (TCP/IP) + consists of an initiator socket ("server") started at a + certain host with a certain port number. A connector socket + ("client"), which is aware of the initiator host name and port + number, can connect to it and data can be sent between + them.

+

Connection-less socket communication (UDP) consists of an + initiator socket at a certain host with a certain port number + and a connector socket sending data to it.

+

For a detailed description of the socket concept, refer to a + suitable book about network programming. A suggestion is + UNIX Network Programming, Volume 1: Networking APIs - + Sockets and XTI by W. Richard Stevens, ISBN: + 013490012X.

+

In Erlang/OTP, access to TCP/IP and UDP sockets is provided + by the modules gen_tcp and gen_udp in + Kernel. Both are easy to use and do not require + detailed knowledge about the socket concept.

+

When to use: For programs running on the same or on + another machine than the Erlang program.

+

Where to read more: See the gen_tcp and the gen_udp manual pages in + Kernel.

IC -

IC (IDL Compiler) is an interface generator which given an IDL interface specification automatically generates stub code in Erlang, C or Java. Please refer to the IC User's Guide and IC Reference Manual.

+

IC (Erlang IDL Compiler) is an interface generator that, given + an IDL interface specification, automatically generates stub + code in Erlang, C, or Java. See the IC User's Guide and IC + Reference Manual.

+

For details, see the ic + manual page in IC.

Old Applications -

There are two old applications of interest when talking about interoperability: IG which was removed in Erlang/OTP R6B and Jive which was removed in Erlang/OTP R7B. Both applications have been replaced by IC and are mentioned here for reference only.

-

IG (Interface Generator) automatically generated code for port or socket communication between an Erlang program and a C program, given a C header file with certain keywords. Jive provided a simple interface between an Erlang program and a Java program.

+

Two old applications are of interest regarding + interoperability. Both have been replaced by IC and are + mentioned here for reference only:

+ +

IG - Removed from Erlang/OTP R6B.

+

IG (Interface Generator) automatically generated code for + port or socket communication between an Erlang program and a + C program, given a C header file with certain keywords.

+
+

Jive - Removed from Erlang/OTP R7B.

+

Jive provided a simple interface between an Erlang program + and a Java program.

+
+
-- cgit v1.2.3