20002021 Ericsson AB. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Erl_Interface erl_interface.xml

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 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:

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

And:

Port ! {self(), {command, encode(Msg)}},
receive
  {Port, {data, Data}} ->
    Caller ! {complex, decode(Data)}
end

is replaced with:

Port ! {self(), {command, term_to_binary(Msg)}},
receive
  {Port, {data, Data}} ->
    Caller ! {complex, binary_to_term(Data)}
end

The resulting Erlang program is as follows:

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 following example shows a C program communicating with an Erlang program over a plain port with the Erlang external term format encoding:

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:

Running the Example

Step 1. Compile the C code. This provides the paths to the include file ei.h, and also to the library ei:

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

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

Eshell V4.9.1.2 (abort with ^G)
1> c(complex2).
{ok,complex2}

Step 3. Run the example:

2> complex2:start("./extprg").
<0.34.0>
3> complex2:foo(3).
4
4> complex2:bar(5).
10
5> complex2:bar(352).
704
6> complex2:stop().
stop