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