1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">
<chapter>
<header>
<copyright>
<year>2000</year><year>2021</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
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.
</legalnotice>
<title>Erl_Interface</title>
<prepared></prepared>
<docno></docno>
<date></date>
<rev></rev>
<file>erl_interface.xml</file>
</header>
<p>This section outlines an example of how to solve the example
problem in <seeguide marker="example">Problem Example</seeguide> by
using a port and Erl_Interface. It is necessary to read the port
example in <seeguide marker="c_port">Ports</seeguide> before reading
this section.</p>
<section>
<title>Erlang Program</title>
<p>The following example shows an Erlang program communicating
with a C program over a plain port with home made encoding:</p>
<codeinclude file="complex1.erl" type="erl"/>
<p>There are two differences when using Erl_Interface on the C
side compared to the example in <seeguide marker="c_port">
Ports</seeguide>, using only the plain port:</p>
<list type="bulleted">
<item>As Erl_Interface operates on the Erlang external term format,
the port must be set to use binaries.</item>
<item>Instead of inventing an encoding/decoding scheme, the
<c>term_to_binary/1</c> and <c>binary_to_term/1</c> BIFs are to
be used.</item>
</list>
<p>That is:</p>
<pre>
open_port({spawn, ExtPrg}, [{packet, 2}])</pre>
<p>is replaced with:</p>
<pre>
open_port({spawn, ExtPrg}, [{packet, 2}, binary])</pre>
<p>And:</p>
<pre>
Port ! {self(), {command, encode(Msg)}},
receive
{Port, {data, Data}} ->
Caller ! {complex, decode(Data)}
end</pre>
<p>is replaced with:</p>
<pre>
Port ! {self(), {command, term_to_binary(Msg)}},
receive
{Port, {data, Data}} ->
Caller ! {complex, binary_to_term(Data)}
end</pre>
<p>The resulting Erlang program is as follows:</p>
<codeinclude file="complex2.erl" type="erl"/>
<p>Notice that calling <c>complex2:foo/1</c> and
<c>complex2:bar/1</c> results in the tuple <c>{foo,X}</c> or
<c>{bar,Y}</c> being sent to the <c>complex</c> 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.</p>
</section>
<section>
<title>C Program</title>
<p>The following example shows a C program communicating with an
Erlang program over a plain port with the Erlang external term format encoding:</p>
<codeinclude file="ei.c" type="c"/>
<p>The following functions, <c>read_cmd()</c> and
<c>write_cmd()</c>, from the <c>erl_comm.c</c> example in
<seeguide marker="c_port">Ports</seeguide> can still be
used for reading from and writing to the port:
</p>
<codeinclude file="erl_comm.c" type="c"/>
</section>
<section>
<title>Running the Example</title>
<p><em>Step 1.</em> Compile the C code. This provides the paths to
the include file <c>ei.h</c>, and
also to the library <c>ei</c>:</p>
<pre>
unix> <input>gcc -o extprg -I/usr/local/otp/lib/erl_interface-3.9.2/include \ </input>
<input> -L/usr/local/otp/lib/erl_interface-3.9.2/lib \ </input>
<input> complex.c erl_comm.c ei.c -lei -lpthread</input></pre>
<p>In Erlang/OTP R5B and later versions of OTP, the <c>include</c>
and <c>lib</c> directories are situated under
<c>OTPROOT/lib/erl_interface-VSN</c>, where <c>OTPROOT</c> is
the root directory of the OTP installation
(<c>/usr/local/otp</c> in the recent example) and <c>VSN</c> is
the version of the Erl_interface application (3.2.1 in the
recent example).</p>
<p>In R4B and earlier versions of OTP, <c>include</c> and <c>lib</c>
are situated under <c>OTPROOT/usr</c>.</p>
<p><em>Step 2.</em> Start Erlang and compile the Erlang code:</p>
<pre>
unix> <input>erl</input>
Erlang (BEAM) emulator version 4.9.1.2
Eshell V4.9.1.2 (abort with ^G)
1> <input>c(complex2).</input>
{ok,complex2}</pre>
<p><em>Step 3.</em> Run the example:</p>
<pre>
2> <input>complex2:start("./extprg").</input>
<0.34.0>
3> <input>complex2:foo(3).</input>
4
4> <input>complex2:bar(5).</input>
10
5> <input>complex2:bar(352).</input>
704
6> <input>complex2:stop().</input>
stop</pre>
</section>
</chapter>
|