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 +++++++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 22 deletions(-) (limited to 'system/doc/tutorial/c_port.xmlsrc') 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>
-- 
cgit v1.2.3