<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Kyle M. Douglass</title><link>http://kmdouglass.github.io/</link><description>Optics, programming, and computer vision.</description><atom:link href="http://kmdouglass.github.io/rss.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Fri, 27 Mar 2020 17:27:59 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Comparison of two methods to append to a list in Python</title><link>http://kmdouglass.github.io/posts/comparison-of-two-methods-to-append-to-a-list-in-python/</link><dc:creator>Kyle M. Douglass</dc:creator><description>&lt;div&gt;&lt;div class="abstract docutils container"&gt;
&lt;p&gt;A colleague recently told me that the &lt;code class="docutils literal"&gt;append&lt;/code&gt; method on a Python
list is more efficient than using the += operator but provided no
justification. Curious, I investigated whether this was true.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="string-validation-as-an-example"&gt;
&lt;h2&gt;String validation as an example&lt;/h2&gt;
&lt;p&gt;Consider the following function as an example. It checks whether a
string is &lt;em&gt;semantically&lt;/em&gt; correct, i.e. whether it satisifies some set of
requirements that are dictated by the needs of the application. In this
example, the requirements are&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;The string cannot be longer than 10 characters&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The string cannot contain a number&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="code python"&gt;&lt;a name="rest_code_1001bcca55fb45a88d7a71b779d09598-1"&gt;&lt;/a&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;
&lt;a name="rest_code_1001bcca55fb45a88d7a71b779d09598-2"&gt;&lt;/a&gt;
&lt;a name="rest_code_1001bcca55fb45a88d7a71b779d09598-3"&gt;&lt;/a&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a name="rest_code_1001bcca55fb45a88d7a71b779d09598-4"&gt;&lt;/a&gt;    &lt;span class="n"&gt;reasons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;a name="rest_code_1001bcca55fb45a88d7a71b779d09598-5"&gt;&lt;/a&gt;
&lt;a name="rest_code_1001bcca55fb45a88d7a71b779d09598-6"&gt;&lt;/a&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a name="rest_code_1001bcca55fb45a88d7a71b779d09598-7"&gt;&lt;/a&gt;        &lt;span class="n"&gt;reasons&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Input is too long"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;a name="rest_code_1001bcca55fb45a88d7a71b779d09598-8"&gt;&lt;/a&gt;
&lt;a name="rest_code_1001bcca55fb45a88d7a71b779d09598-9"&gt;&lt;/a&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s2"&gt;"\d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
&lt;a name="rest_code_1001bcca55fb45a88d7a71b779d09598-10"&gt;&lt;/a&gt;        &lt;span class="n"&gt;reasons&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Input contains a number"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;a name="rest_code_1001bcca55fb45a88d7a71b779d09598-11"&gt;&lt;/a&gt;
&lt;a name="rest_code_1001bcca55fb45a88d7a71b779d09598-12"&gt;&lt;/a&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;reasons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a name="rest_code_1001bcca55fb45a88d7a71b779d09598-13"&gt;&lt;/a&gt;         &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;" | "&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reasons&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;a name="rest_code_1001bcca55fb45a88d7a71b779d09598-14"&gt;&lt;/a&gt;
&lt;a name="rest_code_1001bcca55fb45a88d7a71b779d09598-15"&gt;&lt;/a&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;If either of these conditions are violated, an exception is raised
containing a message. The message describes which condition(s) is(are)
violated. The &lt;code class="docutils literal"&gt;reasons&lt;/code&gt; list contains zero, one, or two elements, and
it is built by appending to the list using the += operator. I could
have instead used the &lt;code class="docutils literal"&gt;append&lt;/code&gt; method of &lt;code class="docutils literal"&gt;list&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="vs-append"&gt;
&lt;h2&gt;+= vs. append&lt;/h2&gt;
&lt;p&gt;To test the speed of the two methods, I use the &lt;code class="docutils literal"&gt;timeit&lt;/code&gt; package from
the Python standard library in the program below. The test consists of
the following:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;Create an empty list&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Append error strings to the list one at a time&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="code python"&gt;&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-1"&gt;&lt;/a&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;string&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-2"&gt;&lt;/a&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;timeit&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-3"&gt;&lt;/a&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-4"&gt;&lt;/a&gt;&lt;span class="n"&gt;reasons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-5"&gt;&lt;/a&gt;    &lt;span class="s2"&gt;"This is an error message"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-6"&gt;&lt;/a&gt;    &lt;span class="s2"&gt;"This is another error message"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-7"&gt;&lt;/a&gt;    &lt;span class="s2"&gt;"Let's add another for good measure"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-8"&gt;&lt;/a&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-9"&gt;&lt;/a&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_plus_equals&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-10"&gt;&lt;/a&gt;    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-11"&gt;&lt;/a&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reasons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-12"&gt;&lt;/a&gt;        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-13"&gt;&lt;/a&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-14"&gt;&lt;/a&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_append&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-15"&gt;&lt;/a&gt;    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-16"&gt;&lt;/a&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reasons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-17"&gt;&lt;/a&gt;        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-18"&gt;&lt;/a&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-19"&gt;&lt;/a&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-20"&gt;&lt;/a&gt;&lt;span class="n"&gt;repeat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-21"&gt;&lt;/a&gt;&lt;span class="n"&gt;results_plus_equals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-22"&gt;&lt;/a&gt;    &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-23"&gt;&lt;/a&gt;        &lt;span class="s2"&gt;"test_plus_equals()"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-24"&gt;&lt;/a&gt;        &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-25"&gt;&lt;/a&gt;        &lt;span class="n"&gt;repeat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-26"&gt;&lt;/a&gt;        &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"from __main__ import test_plus_equals"&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-27"&gt;&lt;/a&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-28"&gt;&lt;/a&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-29"&gt;&lt;/a&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-30"&gt;&lt;/a&gt;&lt;span class="n"&gt;results_append&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-31"&gt;&lt;/a&gt;    &lt;span class="n"&gt;timeit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-32"&gt;&lt;/a&gt;        &lt;span class="s2"&gt;"test_append()"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-33"&gt;&lt;/a&gt;        &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-34"&gt;&lt;/a&gt;        &lt;span class="n"&gt;repeat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-35"&gt;&lt;/a&gt;        &lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"from __main__ import test_append"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-36"&gt;&lt;/a&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-37"&gt;&lt;/a&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-38"&gt;&lt;/a&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"__main__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-39"&gt;&lt;/a&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"1E+6 loops per test"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-40"&gt;&lt;/a&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"+= (best of five tests):&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;{results_plus_equals:0.4f} s"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_351fa1974a9648f194cac3ef35ed9263-41"&gt;&lt;/a&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"append (best of five tests):&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;{results_append:0.4f} s"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="results"&gt;
&lt;h2&gt;Results&lt;/h2&gt;
&lt;pre class="code text"&gt;&lt;a name="rest_code_b7bf81d52bbb401d9b9a9f9de6844e0b-1"&gt;&lt;/a&gt;1E+6 loops per test
&lt;a name="rest_code_b7bf81d52bbb401d9b9a9f9de6844e0b-2"&gt;&lt;/a&gt;+= (best of five tests):     0.2392 s
&lt;a name="rest_code_b7bf81d52bbb401d9b9a9f9de6844e0b-3"&gt;&lt;/a&gt;append (best of five tests): 0.2241 s
&lt;/pre&gt;&lt;p&gt;In this test the &lt;code class="docutils literal"&gt;append&lt;/code&gt; method of Python's list does appear to be
faster by a factor of 6% or 7%. &lt;code class="docutils literal"&gt;append&lt;/code&gt; took about 0.224
microseconds per loop, whereas the += operator took 0.239 microseconds.&lt;/p&gt;
&lt;p&gt;The advantage of the &lt;code class="docutils literal"&gt;append&lt;/code&gt; method is probably only noticeable if
you need to append to a list many millions of times per second.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;</description><category>python</category><guid>http://kmdouglass.github.io/posts/comparison-of-two-methods-to-append-to-a-list-in-python/</guid><pubDate>Fri, 27 Mar 2020 17:09:00 GMT</pubDate></item><item><title>Out of the Tar Pit: a Summary</title><link>http://kmdouglass.github.io/posts/summary-out-of-the-tar-pit/</link><dc:creator>Kyle M. Douglass</dc:creator><description>&lt;div&gt;&lt;p&gt;&lt;a class="reference external" href="http://curtclifton.net/papers/MoseleyMarks06a.pdf"&gt;Out of the Tar Pit&lt;/a&gt; is a 2006 paper by Ben Moseley and Peter Marks about the causes and effects
of complexity in software systems. The thesis of the paper is stated already in the second sentence
of the paper:&lt;/p&gt;
&lt;blockquote&gt;
The biggest problem in the development and maintenance of large-scale software systems is
complexity — large systems are hard to understand.&lt;/blockquote&gt;
&lt;p&gt;As implied by the authors, complexity is a property of a software system that represents the degree
of difficulty that is experienced when trying to understand the system. State—in particular mutable
state—is the primary cause of complexity. Additional causes are code volume and control flow, but
these are of secondary importance.&lt;/p&gt;
&lt;div class="section" id="complexity"&gt;
&lt;h2&gt;Complexity&lt;/h2&gt;
&lt;p&gt;Of the four properties described by Brooks in the paper entitled &lt;a class="reference external" href="https://en.wikipedia.org/wiki/No_Silver_Bullet"&gt;No Silver Bullet&lt;/a&gt; that make
building software hard (complexity, conformity, changeability, invisibility), the authors state
that complexity is the only meaningful one:&lt;/p&gt;
&lt;blockquote&gt;
Complexity is the root cause of the vast majority of problems with software today. Unreliability,
late delivery, lack of security — often even poor performance in large-scale systems can all be
seen as deriving ultimately from unmanageable complexity.&lt;/blockquote&gt;
&lt;p&gt;By complexity, the authors mean "that which makes large systems &lt;em&gt;hard to understand&lt;/em&gt;," not the
field of computer science that is concerned with the resources that are consumed by an algorithm.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="approaches-to-understanding"&gt;
&lt;h2&gt;Approaches to Understanding&lt;/h2&gt;
&lt;p&gt;To better establish their definition of complexity, the authors explore the ways in which
developers attempt to understand a system. There are two main ways:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;strong&gt;Testing&lt;/strong&gt; This is a way to understand the system from the outside.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Informal Reasoning&lt;/strong&gt; This is a way to understand the system from the inside.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
Of the two, informal reasoning is the most important by far. This is because — as we shall see
below — there are inherent limits to what can be achieved by testing, and because informal
reasoning (by virtue of being an inherent part of the development process) is always used.  The
other justification is that improvements in informal reasoning will lead to less errors being
created whilst all that improvements in testing can do is to lead to more errors being detected.&lt;/blockquote&gt;
&lt;p&gt;The primary problem with testing is that a test will only tell you about the behavior of a system
subject to the particular range of inputs used by the test. A test will tell you absolutely nothing
about the system's behavior under a different set of inputs. In large systems, the set of all
possible inputs is too large to fully explore with testing.&lt;/p&gt;
&lt;blockquote&gt;
Have you performed the right tests? The only certain answer you will ever get to this question is
an answer in the negative — when the system breaks.&lt;/blockquote&gt;
&lt;p&gt;Informal reasoning, on the other hand, is what is used when a developer builds a mental model about
how the system works while looking at the code. Because it is the most important way to understand
a system, simplicity is a vital characteristic of well-functioning, large-scale systems.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="causes-of-complexity"&gt;
&lt;h2&gt;Causes of Complexity&lt;/h2&gt;
&lt;div class="section" id="state"&gt;
&lt;h3&gt;State&lt;/h3&gt;
&lt;p&gt;The presence of state (particularly mutable state) makes programs difficult to understand. The
authors offer the following example to explain the problems of state:&lt;/p&gt;
&lt;blockquote&gt;
Anyone who has ever telephoned a support desk for a software system and been told to “try it
again”, or “reload the document”, or “restart the program”, or “reboot your computer” or
“re-install the program” or even “re-install the operating system and then the program” has
direct experience of the problems that state causes for writing reliable, understandable
software.&lt;/blockquote&gt;
&lt;p&gt;State makes testing difficult by making flakiness more likely. (Flakiness describes a set of tests
that randomly fail for seemingly no reason.) This fact, combined with the large number of inputs to
a program, combine together &lt;em&gt;horribly&lt;/em&gt; (emphasis the authors).&lt;/p&gt;
&lt;p&gt;In addition, state complicates informal reasoning by hindering the developer from understanding the
system "from the inside." It contaminates a system in the sense that even mostly stateless systems
become difficult to understand when coupled to components with mutable state.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="control"&gt;
&lt;h3&gt;Control&lt;/h3&gt;
&lt;p&gt;The authors claim that the next most important barrier to understanding is control.&lt;/p&gt;
&lt;blockquote&gt;
Control is basically about the order in which things happen. The problem with control is that
very often we do not want to have to be concerned with this.&lt;/blockquote&gt;
&lt;p&gt;Complexity caused by control very much depends on the choice of language; some languages make
control flow explicit, whereas other, more declarative languages, make control flow
implicit. Having to explicitly deal with control creates complexity.&lt;/p&gt;
&lt;p&gt;The same is true of concurrency. Explicit concurrency in particular makes both testing and informal
reasoning about programs hard.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="code-volume"&gt;
&lt;h3&gt;Code volume&lt;/h3&gt;
&lt;p&gt;Increasing the amount of code does increase complexity, but effective management of state and
control marginalizes its impact.&lt;/p&gt;
&lt;p&gt;There are indeed other causes of complexity than the three listed above, but they all reduce to
three basic principles:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Complexity breeds complexity&lt;/li&gt;
&lt;li&gt;Simplicity is &lt;em&gt;hard&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Power corrupts&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The last principle states that mistakes and poor decisions &lt;em&gt;will be made&lt;/em&gt; when a language allows
it. For this reason, restrictive, declarative languages and tools should be preferred.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="classical-approaches-to-managing-complexity"&gt;
&lt;h2&gt;Classical approaches to managing complexity&lt;/h2&gt;
&lt;p&gt;To better understand the ways in which programmers manage complexity, the authors explore three
major styles of programming:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Imperative (more precisely, object-oriented)&lt;/li&gt;
&lt;li&gt;Functional&lt;/li&gt;
&lt;li&gt;Logic&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="section" id="object-orientation"&gt;
&lt;h3&gt;Object-orientation&lt;/h3&gt;
&lt;p&gt;Object-oriented programming (OOP) is one of the most dominant styles of programming today for
computers that are based on the von Neumann architecture and is presumably inspired largely by its
state-based form of computation.&lt;/p&gt;
&lt;p&gt;OOP enforces integrity constraints on data by combining an object's state with a set of procedures
to access and modify it. This characteristic is known as &lt;em&gt;encapsulation&lt;/em&gt;. Problems may arise when
multiple procedures contend for access to the same state.&lt;/p&gt;
&lt;p&gt;OOP also views objects as being uniquely identifiable, regardless of the object's attributes. In
other words, two objects with the exact same set of attributes and values are condsidered
distinct. This property is known as &lt;em&gt;intensional identity&lt;/em&gt; and contrasts with &lt;em&gt;extensional
identity&lt;/em&gt; in which things are considered the same if their attributes are the same.&lt;/p&gt;
&lt;p&gt;For these two reasons, OOP is not suitable for avoiding the problems of complexity:&lt;/p&gt;
&lt;blockquote&gt;
The bottom line is that all forms of OOP rely on state (contained within objects) and in general
all behaviour is affected by this state. As a result of this, OOP suffers directly from the
problems associated with state described above, and as such we believe that it does not provide
an adequate foundation for avoiding complexity.&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class="section" id="functional-programming"&gt;
&lt;h3&gt;Functional programming&lt;/h3&gt;
&lt;p&gt;Modern functional programming (FP) languages can be classified as pure (e.g. Haskell) and impure
(e.g. the ML family of languages).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The primary strength of functional programming is that by avoiding state (and side-effects) the
entire system gains the property of &lt;em&gt;referential transparency&lt;/em&gt; - which implies that when supplied
with a given set of arguments a function will always return exactly the same result (speaking
loosely we could say that it will always behave in the same way)...&lt;/p&gt;
&lt;p&gt;It is this cast iron guarantee of &lt;em&gt;referential transparency&lt;/em&gt; that obliterates one of the two
crucial weaknesses of testing as discussed above. As a result, even though the other weakness of
testing remains (testing for one set of inputs says nothing at all about behaviour with another
set of inputs), testing does become far more effective if a system has been developed in a
functional style.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Informal reasoning is also more effective in the functional approach to programming. By enforcing
&lt;em&gt;referential transparency&lt;/em&gt;, mutable state is generally avoided. However, in spite of its
properties, nothing in FP can prevent somenone from effectively simulating multiple state, so some
care must still be taken.&lt;/p&gt;
&lt;p&gt;The authors concede that by sacrificing state in FP, one does lose a degree of modularity.&lt;/p&gt;
&lt;blockquote&gt;
Working within a stateful framework it is possible to add state to any component without
adjusting the components which invoke it. Working within a functional framework the same effect
can only be achieved by adjusting every single component that invokes it to carry the additional
information around.&lt;/blockquote&gt;
&lt;p&gt;However,&lt;/p&gt;
&lt;blockquote&gt;
The trade-off is between complexity (with the ability to take a shortcut when making some
specific types of change) and simplicity (with huge improvements in both testing and
reasoning). As with the discipline of (static) typing, it is trading a one-off up-front cost for
continuing future gains and safety (“one-off” because each piece of code is written once but is
read, reasoned about and tested on a continuing basis).&lt;/blockquote&gt;
&lt;p&gt;FP remains relatively unpopular despite its advantages. The authors state that the reason is that
problems arise when programmers attempt to use it in problems that require mutable state.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="logic-programming"&gt;
&lt;h3&gt;Logic programming&lt;/h3&gt;
&lt;p&gt;Logic programming is like FP in the sense that it is declarative: it emphasizes what needs to be
done, not how it is done. The primary example of a logic programming language is Prolog.&lt;/p&gt;
&lt;blockquote&gt;
Pure logic programming is the approach of doing nothing more than making statements about the
problem (and desired solutions). This is done by stating a set of axioms which describe the
problem and the attributes required of something for it to be considered a solution. The ideal of
logic programming is that there should be an infrastructure which can take the raw axioms and use
them to find or check solutions. All solutions are formal logical consequences of the axioms
supplied, and “running” the system is equivalent to the construction of a formal proof of each
solution.&lt;/blockquote&gt;
&lt;p&gt;Pure logic programming does not suffer from the same problems of state and control as OOP. However,
it appears that real logic programming languages need to make some pragmatic tradeoffs in their
implementations which introducs small amounts of state and control elements.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="accidents-and-essence"&gt;
&lt;h2&gt;Accidents and Essence&lt;/h2&gt;
&lt;p&gt;The authors define two different types of complexity:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;strong&gt;Essential complexity&lt;/strong&gt; is inherent in, and the essence of, the problem as seen by the user.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Accidental complexity&lt;/strong&gt; is all the rest - complexity with which the development team would not
have to deal with in the real world.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is important to understand the degree of strictness in the definition of essential
complexity. Only complexity related to the problem domain of the user falls into this
category. Everything related to the implementation details - bytes, transistors, operating systems,
programming languages, etc. - is accidental complexity.&lt;/p&gt;
&lt;blockquote&gt;
We hence see essential complexity as "the complexity with which the team will have to be
concerned, even in the ideal world"... Note that the "have to" part of this observation is
critical — if there is any possible way that the team could produce a system that the users will
consider correct without having to be concerned with a given type of complexity then that
complexity is not essential.&lt;/blockquote&gt;
&lt;p&gt;The authors disagree with Brooks's assertion that most complexity in software is essential.&lt;/p&gt;
&lt;blockquote&gt;
Complexity itself is not an inherent (or essential) property of software (it is perfectly
possible to write software which is simple and yet is still software), and further, much
complexity that we do see in existing software is not essential (to the problem).&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class="section" id="recommended-general-approach"&gt;
&lt;h2&gt;Recommended general approach&lt;/h2&gt;
&lt;p&gt;The remaining sections of the paper present the authors' idea on a model system that minimizes the
effects of complexity. First, they present the solution in the ideal world, and then adjust this
solution accordingly to handle real world constraints.&lt;/p&gt;
&lt;div class="section" id="ideal-world"&gt;
&lt;h3&gt;Ideal world&lt;/h3&gt;
&lt;p&gt;The implementation of a complexity-minimizing system in the ideal world is not concerned with
performance, and the language and infrastructure provides all the support necessary to build the
system.&lt;/p&gt;
&lt;p&gt;The purpose of designing the system is to translate users' informal requirements into formal
requirements.&lt;/p&gt;
&lt;div class="math"&gt;
\begin{equation*}
\text{Informal requirements} \rightarrow \text{Formal requirements}
\end{equation*}
&lt;/div&gt;
&lt;p&gt;(Note that I believe that, today, this mapping is most often done as part of the Agile workflow,
not through a formal analysis method.) In the ideal world, this translation must not introduce any
accidental complexity, and, as a result, should not include any details about execution
what-so-ever.&lt;/p&gt;
&lt;blockquote&gt;
The sole concern when producing the formal requirements must be to ensure that there is no
relevant ambiguity in the informal requirements (i.e. that it has no omissions).&lt;/blockquote&gt;
&lt;p&gt;Once the design process has finished, it should suffice to simply execute the system in the ideal
world.&lt;/p&gt;
&lt;p&gt;Such a system as described above obtains its data either as inputs or by deriving it from
inputs. All data derived from the user requirements is essential, but not all such data corresponds
to &lt;em&gt;essential state&lt;/em&gt;. The reason is that some derived data need not be stored but, rather,
calculated only as needed.&lt;/p&gt;
&lt;p&gt;Only essential input data corresponds to essential state. All other data is part of accidental
state, including:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;derived, immutable, essential data&lt;/li&gt;
&lt;li&gt;derived, mutable, essential data&lt;/li&gt;
&lt;li&gt;and derived accidental data.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Control in the ideal world is entirely accidental; it is not something that programmer's should be
concerned with (in the ideal world!) because it does not pertain to the users' problem.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="required-accidental-complexity"&gt;
&lt;h3&gt;Required Accidental Complexity&lt;/h3&gt;
&lt;p&gt;Once we move into the real world, we will find that we must allow for some accidental
complexity. The reasons for justifying it are&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Ease of expression&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Given that we must allow for some accidental complexity, the authors suggest the following strategy
to address it:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Avoid&lt;/li&gt;
&lt;li&gt;Separate&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The overriding aim must be to avoid accidental complexity and, when it is necessary, separate it
from the rest of the system to the greatest degree possible.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="functional-relational-programming"&gt;
&lt;h2&gt;Functional relational programming&lt;/h2&gt;
&lt;p&gt;The second part of the paper concerns itself with exploring a real-world implementation of a
complexity-minimizing system known as &lt;em&gt;functional relational programming&lt;/em&gt;, or FRP. It is based on
two major paradigms:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;the relational data model for handling state&lt;/li&gt;
&lt;li&gt;pure functional programming for handling logic&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Throughout these final sections, the role of the relational model was the primary topic, whereas
the role of functional programming within the system was given relatively little importance. I
found a few points interesting here:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;The authors focus primarily on the pure form of the relational model, citing &lt;a class="reference external" href="https://dl.acm.org/doi/10.5555/77708.C1065772"&gt;a work of Codd's&lt;/a&gt;
that criticizes "impure" but pragmatic implementations, such as SQL. However, and as far as I
can tell, there are extremely few real-world implementations of a pure relational database. (I
only managed to find one, &lt;a class="reference external" href="https://reldb.org/c/"&gt;RelDB&lt;/a&gt;, from &lt;a class="reference external" href="https://www.sisense.com/blog/your-database-isnt-really-relational/"&gt;a page explaining why and how&lt;/a&gt; SQL does not strictly
follow the relational model.)&lt;/li&gt;
&lt;li&gt;In spite of the paper's insistence on the elimination of mutable state, it seems like the
authors ignore the point that their implementation of essential state using the relational model
is mutable. I know of no way that FRP can update the relational variables in the system's
essential state without mutating them.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The following quotes indicate that the authors seem to understand that their system is based on
mutable state, which is why I am puzzled that it is part of their proposed solution.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Specifically, all input must be converted into relational assignments (which replace the old
relvar values in the essential state with new ones), and all output (and side-effects) must be
driven from changes to the values of relvars (primarily derived relvars). - Section 9.1.4&lt;/p&gt;
&lt;p&gt;Finally, the ability to access arbitrary historical relvar values would obviously be a useful
extension in some scenarios. - Section 9.1.5&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I was actually a bit relieved when a colleague pointed out to me that Rich Hickey expresses similar
criticism about FRP in his talk &lt;a class="reference external" href="https://www.youtube.com/watch?v=Cym4TZwTCNU"&gt;Deconstructing the Database&lt;/a&gt; because it gave me some confidence
that my suspicions may be correct.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="summary"&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;"Out of the Tar Pit" has significantly changed the way I think about solving problems with software
engineering. In particular, it has made me reevaluate the signifance of domain specific languages
(DSLs), especially those that constrain the freedom of the programmer to work only within the
problem's immediate domain. I am much more suspect of the tendency of programmers to focus on the
flow of control in a program, and I now go to great lengths to avoid mutable state in my own work.&lt;/p&gt;
&lt;p&gt;I invested the most thought in the final sections of the paper, only to conclude that their
content, in my opinion, is somewhat incomplete. Though the relational model is indeed powerful and
elegant, it has very few pure, real-world implementations and seems to admit mutable state. This
last bit I find difficult to reconcile with the main thesis of the paper, which is that mutable
state is the primary cause of complexity in systems.&lt;/p&gt;
&lt;p&gt;I described "Out of the Tar Pit" to my former manager as one of those papers where if you read it,
you can't help but agree with it's message because it puts into words what you already know by
heart. He replied that this is true only if you've worked in programming for long enough to suffer
from the effects of unmanageable complexity. Otherwise, you have no idea what the authors are
talking about.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;</description><category>literature summary</category><guid>http://kmdouglass.github.io/posts/summary-out-of-the-tar-pit/</guid><pubDate>Fri, 28 Feb 2020 22:40:18 GMT</pubDate></item><item><title>Variable locations in Rust during copy and move</title><link>http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/</link><dc:creator>Kyle M. Douglass</dc:creator><description>&lt;div&gt;&lt;p&gt;&lt;a class="reference external" href="https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html"&gt;Ownership&lt;/a&gt; is a well-known concept in Rust and is a major reason for the language's memory
safety. Consider the following example of ownership from &lt;a class="reference external" href="https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html#memory-and-allocation"&gt;The Rust Programming Language&lt;/a&gt;:&lt;/p&gt;
&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_ab8c77e60e9b49cd8f0baa547a637da0-1"&gt;1&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_ab8c77e60e9b49cd8f0baa547a637da0-2"&gt;2&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_ab8c77e60e9b49cd8f0baa547a637da0-3"&gt;3&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_ab8c77e60e9b49cd8f0baa547a637da0-4"&gt;4&lt;/a&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="code rust"&gt;&lt;a name="rest_code_ab8c77e60e9b49cd8f0baa547a637da0-1"&gt;&lt;/a&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;::&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_ab8c77e60e9b49cd8f0baa547a637da0-2"&gt;&lt;/a&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_ab8c77e60e9b49cd8f0baa547a637da0-3"&gt;&lt;/a&gt;
&lt;a name="rest_code_ab8c77e60e9b49cd8f0baa547a637da0-4"&gt;&lt;/a&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}, world!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;Compiling this code will produce an error because the &lt;tt class="docutils literal"&gt;String&lt;/tt&gt; value that is bound to the
variable &lt;tt class="docutils literal"&gt;s1&lt;/tt&gt; is moved to &lt;tt class="docutils literal"&gt;s2&lt;/tt&gt;. After a move, you may no longer use the value bound to
&lt;tt class="docutils literal"&gt;s1&lt;/tt&gt;. (You may, as we will see, re-use its memory by binding a new value of the same type to it.)&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;String&lt;/tt&gt; is a container type, which means that it contains both metadata on the stack and a
pointer to data on the heap. Simple types such as &lt;tt class="docutils literal"&gt;i32&lt;/tt&gt;, on the other hand, are normally stored
entirely on the stack. Types such as these implement the &lt;a class="reference external" href="https://doc.rust-lang.org/std/marker/trait.Copy.html"&gt;Copy&lt;/a&gt; trait. This means that variable
reassignment does not produce a compile-time error like it does in the example above:&lt;/p&gt;
&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_0f0822f5f2ce4f43a17dffeb09cd8225-1"&gt;1&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_0f0822f5f2ce4f43a17dffeb09cd8225-2"&gt;2&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_0f0822f5f2ce4f43a17dffeb09cd8225-3"&gt;3&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_0f0822f5f2ce4f43a17dffeb09cd8225-4"&gt;4&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_0f0822f5f2ce4f43a17dffeb09cd8225-5"&gt;5&lt;/a&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="code rust"&gt;&lt;a name="rest_code_0f0822f5f2ce4f43a17dffeb09cd8225-1"&gt;&lt;/a&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_0f0822f5f2ce4f43a17dffeb09cd8225-2"&gt;&lt;/a&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_0f0822f5f2ce4f43a17dffeb09cd8225-3"&gt;&lt;/a&gt;
&lt;a name="rest_code_0f0822f5f2ce4f43a17dffeb09cd8225-4"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// The value bound to x is Copy, so no error will be raised.&lt;/span&gt;
&lt;a name="rest_code_0f0822f5f2ce4f43a17dffeb09cd8225-5"&gt;&lt;/a&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;&lt;tt class="docutils literal"&gt;String&lt;/tt&gt; is not &lt;tt class="docutils literal"&gt;Copy&lt;/tt&gt; because it contains a pointer to data on the heap. When a variable that
is bound to a &lt;tt class="docutils literal"&gt;String&lt;/tt&gt; is dropped, its data is automatically freed from the heap. If a &lt;tt class="docutils literal"&gt;String&lt;/tt&gt;
were &lt;tt class="docutils literal"&gt;Copy&lt;/tt&gt;, the compiler would have to determine whether the heap data is still pointed to by
another variable to avoid a &lt;a class="reference external" href="https://stackoverflow.com/questions/21057393/what-does-double-free-mean"&gt;double free error&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="memory-layout-in-copies-and-moves"&gt;
&lt;h2&gt;Memory layout in copies and moves&lt;/h2&gt;
&lt;p&gt;What's happening inside a program's memory during copies and moves? Consider first a move:&lt;/p&gt;
&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_76df2b45730a42f9b75d3349dbe0887b-1"&gt; 1&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_76df2b45730a42f9b75d3349dbe0887b-2"&gt; 2&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_76df2b45730a42f9b75d3349dbe0887b-3"&gt; 3&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_76df2b45730a42f9b75d3349dbe0887b-4"&gt; 4&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_76df2b45730a42f9b75d3349dbe0887b-5"&gt; 5&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_76df2b45730a42f9b75d3349dbe0887b-6"&gt; 6&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_76df2b45730a42f9b75d3349dbe0887b-7"&gt; 7&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_76df2b45730a42f9b75d3349dbe0887b-8"&gt; 8&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_76df2b45730a42f9b75d3349dbe0887b-9"&gt; 9&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_76df2b45730a42f9b75d3349dbe0887b-10"&gt;10&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_76df2b45730a42f9b75d3349dbe0887b-11"&gt;11&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_76df2b45730a42f9b75d3349dbe0887b-12"&gt;12&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_76df2b45730a42f9b75d3349dbe0887b-13"&gt;13&lt;/a&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="code rust"&gt;&lt;a name="rest_code_76df2b45730a42f9b75d3349dbe0887b-1"&gt;&lt;/a&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;::&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_76df2b45730a42f9b75d3349dbe0887b-2"&gt;&lt;/a&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Memory address of x: {:p}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_76df2b45730a42f9b75d3349dbe0887b-3"&gt;&lt;/a&gt;
&lt;a name="rest_code_76df2b45730a42f9b75d3349dbe0887b-4"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// Move occurs here&lt;/span&gt;
&lt;a name="rest_code_76df2b45730a42f9b75d3349dbe0887b-5"&gt;&lt;/a&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_76df2b45730a42f9b75d3349dbe0887b-6"&gt;&lt;/a&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Memory address of y: {:p}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_76df2b45730a42f9b75d3349dbe0887b-7"&gt;&lt;/a&gt;
&lt;a name="rest_code_76df2b45730a42f9b75d3349dbe0887b-8"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// Printing the memory address of x is an error because its value was moved.&lt;/span&gt;
&lt;a name="rest_code_76df2b45730a42f9b75d3349dbe0887b-9"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// println!("Memory address of x: {:p}", &amp;amp;x)&lt;/span&gt;
&lt;a name="rest_code_76df2b45730a42f9b75d3349dbe0887b-10"&gt;&lt;/a&gt;
&lt;a name="rest_code_76df2b45730a42f9b75d3349dbe0887b-11"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// Assign new string to x&lt;/span&gt;
&lt;a name="rest_code_76df2b45730a42f9b75d3349dbe0887b-12"&gt;&lt;/a&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;::&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_76df2b45730a42f9b75d3349dbe0887b-13"&gt;&lt;/a&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Memory address of x: {:p}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;In the above code snippet, addresses of variables are printed by using the pointer formatter
&lt;tt class="docutils literal"&gt;:p&lt;/tt&gt;. I create a &lt;tt class="docutils literal"&gt;String&lt;/tt&gt; value and bind it to the variable &lt;tt class="docutils literal"&gt;x&lt;/tt&gt;. Then, the value is moved to
the variable &lt;tt class="docutils literal"&gt;y&lt;/tt&gt; which prevents me from using &lt;tt class="docutils literal"&gt;x&lt;/tt&gt; again in the &lt;tt class="docutils literal"&gt;println!&lt;/tt&gt; macro.&lt;/p&gt;
&lt;p&gt;However, I can assign a new &lt;tt class="docutils literal"&gt;String&lt;/tt&gt; value to &lt;tt class="docutils literal"&gt;x&lt;/tt&gt; by reusing its memory on the stack. This does
not change its memory address as seen in the output below:&lt;/p&gt;
&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_61bb6e1f1c1d4730b49b2d79e19d0ca4-1"&gt;1&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_61bb6e1f1c1d4730b49b2d79e19d0ca4-2"&gt;2&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_61bb6e1f1c1d4730b49b2d79e19d0ca4-3"&gt;3&lt;/a&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="code console"&gt;&lt;a name="rest_code_61bb6e1f1c1d4730b49b2d79e19d0ca4-1"&gt;&lt;/a&gt;&lt;span class="go"&gt;Memory address of x: 0x7ffded2aa3d0&lt;/span&gt;
&lt;a name="rest_code_61bb6e1f1c1d4730b49b2d79e19d0ca4-2"&gt;&lt;/a&gt;&lt;span class="go"&gt;Memory address of y: 0x7ffded2aa3f0&lt;/span&gt;
&lt;a name="rest_code_61bb6e1f1c1d4730b49b2d79e19d0ca4-3"&gt;&lt;/a&gt;&lt;span class="go"&gt;Memory address of x: 0x7ffded2aa3d0  # Memory address of x is unchanged after reassignment&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;A copy is similar. In the snippet below, an integer that is originally bound to &lt;tt class="docutils literal"&gt;x&lt;/tt&gt; is copied to
&lt;tt class="docutils literal"&gt;y&lt;/tt&gt;, which means that I can still refer to &lt;tt class="docutils literal"&gt;x&lt;/tt&gt; in the &lt;tt class="docutils literal"&gt;println!&lt;/tt&gt; macro.&lt;/p&gt;
&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_cf3cd4b3be734d1c997ab1317439eff0-1"&gt; 1&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_cf3cd4b3be734d1c997ab1317439eff0-2"&gt; 2&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_cf3cd4b3be734d1c997ab1317439eff0-3"&gt; 3&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_cf3cd4b3be734d1c997ab1317439eff0-4"&gt; 4&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_cf3cd4b3be734d1c997ab1317439eff0-5"&gt; 5&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_cf3cd4b3be734d1c997ab1317439eff0-6"&gt; 6&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_cf3cd4b3be734d1c997ab1317439eff0-7"&gt; 7&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_cf3cd4b3be734d1c997ab1317439eff0-8"&gt; 8&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_cf3cd4b3be734d1c997ab1317439eff0-9"&gt; 9&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_cf3cd4b3be734d1c997ab1317439eff0-10"&gt;10&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_cf3cd4b3be734d1c997ab1317439eff0-11"&gt;11&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_cf3cd4b3be734d1c997ab1317439eff0-12"&gt;12&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_cf3cd4b3be734d1c997ab1317439eff0-13"&gt;13&lt;/a&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="code rust"&gt;&lt;a name="rest_code_cf3cd4b3be734d1c997ab1317439eff0-1"&gt;&lt;/a&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_cf3cd4b3be734d1c997ab1317439eff0-2"&gt;&lt;/a&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Memory address of x: {:p}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_cf3cd4b3be734d1c997ab1317439eff0-3"&gt;&lt;/a&gt;
&lt;a name="rest_code_cf3cd4b3be734d1c997ab1317439eff0-4"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// Move occurs here&lt;/span&gt;
&lt;a name="rest_code_cf3cd4b3be734d1c997ab1317439eff0-5"&gt;&lt;/a&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_cf3cd4b3be734d1c997ab1317439eff0-6"&gt;&lt;/a&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Memory address of y: {:p}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_cf3cd4b3be734d1c997ab1317439eff0-7"&gt;&lt;/a&gt;
&lt;a name="rest_code_cf3cd4b3be734d1c997ab1317439eff0-8"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// Printing the memory address of x is not an error because its value was copied.&lt;/span&gt;
&lt;a name="rest_code_cf3cd4b3be734d1c997ab1317439eff0-9"&gt;&lt;/a&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Memory address of x: {:p}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_cf3cd4b3be734d1c997ab1317439eff0-10"&gt;&lt;/a&gt;
&lt;a name="rest_code_cf3cd4b3be734d1c997ab1317439eff0-11"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// Assign new integer to x&lt;/span&gt;
&lt;a name="rest_code_cf3cd4b3be734d1c997ab1317439eff0-12"&gt;&lt;/a&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_cf3cd4b3be734d1c997ab1317439eff0-13"&gt;&lt;/a&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Memory address of x: {:p}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;Both the copy operation and value reassignment do not change the memory locations of &lt;tt class="docutils literal"&gt;x&lt;/tt&gt; as seen
in the program's output:&lt;/p&gt;
&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_7bcef0c364664af6b1db61f2cc8d9f81-1"&gt;1&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_7bcef0c364664af6b1db61f2cc8d9f81-2"&gt;2&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_7bcef0c364664af6b1db61f2cc8d9f81-3"&gt;3&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/#rest_code_7bcef0c364664af6b1db61f2cc8d9f81-4"&gt;4&lt;/a&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="code console"&gt;&lt;a name="rest_code_7bcef0c364664af6b1db61f2cc8d9f81-1"&gt;&lt;/a&gt;&lt;span class="go"&gt;Memory address of x: 0x7ffee579d544&lt;/span&gt;
&lt;a name="rest_code_7bcef0c364664af6b1db61f2cc8d9f81-2"&gt;&lt;/a&gt;&lt;span class="go"&gt;Memory address of y: 0x7ffee579d548&lt;/span&gt;
&lt;a name="rest_code_7bcef0c364664af6b1db61f2cc8d9f81-3"&gt;&lt;/a&gt;&lt;span class="go"&gt;Memory address of x: 0x7ffee579d544  # Memory address of x is unchanged after copy&lt;/span&gt;
&lt;a name="rest_code_7bcef0c364664af6b1db61f2cc8d9f81-4"&gt;&lt;/a&gt;&lt;span class="go"&gt;Memory address of x: 0x7ffee579d544  # Memory address of x is unchanged after reassignment&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;div class="section" id="summary"&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;Move semantics on container types are one of the reasons for Rust's memory safety. Nothing
mysterious is happening in memory when a value is moved from one location to another. The original
stack memory still exists; its use is simply disallowed by the compiler until a new value is
assigned to it.&lt;/p&gt;
&lt;p&gt;The complete program from this post may be found here:
&lt;a class="reference external" href="https://gist.github.com/kmdouglass/e596d0934e15f6b3a96c1eca6f6cd999"&gt;https://gist.github.com/kmdouglass/e596d0934e15f6b3a96c1eca6f6cd999&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;</description><category>rust</category><guid>http://kmdouglass.github.io/posts/variable-locations-in-rust-during-copy-and-move/</guid><pubDate>Sun, 24 Nov 2019 09:46:20 GMT</pubDate></item><item><title>A simple plugin interface for the Rust FFI</title><link>http://kmdouglass.github.io/posts/a-simple-plugin-interface-for-the-rust-ffi/</link><dc:creator>Kyle M. Douglass</dc:creator><description>&lt;div&gt;&lt;p&gt;In a recent post I explored &lt;a class="reference external" href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/"&gt;how to pass complex datatypes through the Rust FFI&lt;/a&gt;. (The FFI is the
foreign function interface, a part of the Rust language for calling code written in other
languages.)&lt;/p&gt;
&lt;p&gt;I am exploring the Rust FFI because I want to use it in &lt;a class="reference external" href="https://github.com/kmdouglass/kpal"&gt;a small web application&lt;/a&gt; that I am
writing and that will be used to interact with hardware peripherals connected to a system on a chip
(SoC). One use-case that I have in mind is to monitor readings from moisture and temperature
sensors implanted in the soil of my houseplants. In many cases the general purpose input/output
(GPIO) pins of a SoC are controlled through a C library such as &lt;a class="reference external" href="http://wiringpi.com"&gt;WiringPi&lt;/a&gt; for the Raspberry Pi,
which means my monitoring system needs to interface with C libraries such as this one.&lt;/p&gt;
&lt;p&gt;In this post I will describe my current understanding for how best to integrate C-language plugins
with a Rust application. I have omitted all application-specific logic from the example and will
instead focus on the design of the plugin interface itself.&lt;/p&gt;
&lt;p&gt;You may find &lt;a class="reference external" href="https://github.com/kmdouglass/rust-libloading-example"&gt;the source code for this post here&lt;/a&gt;. I was heavily inspired by both the &lt;a class="reference external" href="http://jakegoulding.com/rust-ffi-omnibus/"&gt;Rust FFI
Omnibus&lt;/a&gt; and &lt;a class="reference external" href="https://michael-f-bryan.github.io/rust-ffi-guide/"&gt;The (unofficial) Rust FFI Guide&lt;/a&gt;. This post was written using version 1.35.0 of the
Rust compiler.&lt;/p&gt;
&lt;div class="section" id="the-c-plugin"&gt;
&lt;h2&gt;The C plugin&lt;/h2&gt;
&lt;p&gt;I wrote a very simple of C library that is located in the &lt;a class="reference external" href="https://github.com/kmdouglass/rust-libloading-example/tree/master/ffi-test"&gt;ffi-test&lt;/a&gt; folder of the example
repository and that will serve the purpose of this demonstration. It consists of two source files
(&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ffi-test.c&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ffi-test.h&lt;/span&gt;&lt;/tt&gt;) and a &lt;tt class="docutils literal"&gt;Makefile&lt;/tt&gt;. The plugin's interface is defined as usual
in the header file:&lt;/p&gt;
&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;a href="http://kmdouglass.github.io/posts/a-simple-plugin-interface-for-the-rust-ffi/#rest_code_3229f5ca334f4d2faab09a82f880df02-1"&gt; 1&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-plugin-interface-for-the-rust-ffi/#rest_code_3229f5ca334f4d2faab09a82f880df02-2"&gt; 2&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-plugin-interface-for-the-rust-ffi/#rest_code_3229f5ca334f4d2faab09a82f880df02-3"&gt; 3&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-plugin-interface-for-the-rust-ffi/#rest_code_3229f5ca334f4d2faab09a82f880df02-4"&gt; 4&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-plugin-interface-for-the-rust-ffi/#rest_code_3229f5ca334f4d2faab09a82f880df02-5"&gt; 5&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-plugin-interface-for-the-rust-ffi/#rest_code_3229f5ca334f4d2faab09a82f880df02-6"&gt; 6&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-plugin-interface-for-the-rust-ffi/#rest_code_3229f5ca334f4d2faab09a82f880df02-7"&gt; 7&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-plugin-interface-for-the-rust-ffi/#rest_code_3229f5ca334f4d2faab09a82f880df02-8"&gt; 8&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-plugin-interface-for-the-rust-ffi/#rest_code_3229f5ca334f4d2faab09a82f880df02-9"&gt; 9&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-plugin-interface-for-the-rust-ffi/#rest_code_3229f5ca334f4d2faab09a82f880df02-10"&gt;10&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-plugin-interface-for-the-rust-ffi/#rest_code_3229f5ca334f4d2faab09a82f880df02-11"&gt;11&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-plugin-interface-for-the-rust-ffi/#rest_code_3229f5ca334f4d2faab09a82f880df02-12"&gt;12&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-plugin-interface-for-the-rust-ffi/#rest_code_3229f5ca334f4d2faab09a82f880df02-13"&gt;13&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-plugin-interface-for-the-rust-ffi/#rest_code_3229f5ca334f4d2faab09a82f880df02-14"&gt;14&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-plugin-interface-for-the-rust-ffi/#rest_code_3229f5ca334f4d2faab09a82f880df02-15"&gt;15&lt;/a&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="code c"&gt;&lt;a name="rest_code_3229f5ca334f4d2faab09a82f880df02-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#ifndef FFI_TEST_H&lt;/span&gt;
&lt;a name="rest_code_3229f5ca334f4d2faab09a82f880df02-2"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#define FFI_TEST_H&lt;/span&gt;
&lt;a name="rest_code_3229f5ca334f4d2faab09a82f880df02-3"&gt;&lt;/a&gt;
&lt;a name="rest_code_3229f5ca334f4d2faab09a82f880df02-4"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
&lt;a name="rest_code_3229f5ca334f4d2faab09a82f880df02-5"&gt;&lt;/a&gt;
&lt;a name="rest_code_3229f5ca334f4d2faab09a82f880df02-6"&gt;&lt;/a&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_3229f5ca334f4d2faab09a82f880df02-7"&gt;&lt;/a&gt;
&lt;a name="rest_code_3229f5ca334f4d2faab09a82f880df02-8"&gt;&lt;/a&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_3229f5ca334f4d2faab09a82f880df02-9"&gt;&lt;/a&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;free_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_3229f5ca334f4d2faab09a82f880df02-10"&gt;&lt;/a&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;get_api_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_3229f5ca334f4d2faab09a82f880df02-11"&gt;&lt;/a&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;get_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_3229f5ca334f4d2faab09a82f880df02-12"&gt;&lt;/a&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;set_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_3229f5ca334f4d2faab09a82f880df02-13"&gt;&lt;/a&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="nf"&gt;sizeof_obj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_3229f5ca334f4d2faab09a82f880df02-14"&gt;&lt;/a&gt;
&lt;a name="rest_code_3229f5ca334f4d2faab09a82f880df02-15"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#endif &lt;/span&gt;&lt;span class="cm"&gt;/* FFI_TEST_H */&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;In particular, there is an opaque struct that is declared by the line &lt;code&gt;struct object;&lt;/code&gt;. (An
opaque struct is a struct whose definition is hidden from the public API; the definition is
provided in the file &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ffi-test.c&lt;/span&gt;&lt;/tt&gt;.) This object will hold the data for our plugin, but, because
it is opaque, we will only be able to interact with it through functions such as &lt;tt class="docutils literal"&gt;init&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;free_object&lt;/tt&gt;, etc. that are provided by the API.&lt;/p&gt;
&lt;p&gt;To build the C library on UNIX-like systems, simply execute the &lt;tt class="docutils literal"&gt;make&lt;/tt&gt; command from within the
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ffi-test&lt;/span&gt;&lt;/tt&gt; library.&lt;/p&gt;
&lt;pre class="code console"&gt;&lt;a name="rest_code_d952c6d87ba5421786543314ce9f4b86-1"&gt;&lt;/a&gt;&lt;span class="gp"&gt;$&lt;/span&gt; make
&lt;a name="rest_code_d952c6d87ba5421786543314ce9f4b86-2"&gt;&lt;/a&gt;&lt;span class="go"&gt;gcc -c -o libffi-test.o -fpic ffi-test.c -Wall -Werror&lt;/span&gt;
&lt;a name="rest_code_d952c6d87ba5421786543314ce9f4b86-3"&gt;&lt;/a&gt;&lt;span class="go"&gt;gcc -shared -o libffi-test.so libffi-test.o&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="the-rust-c-plugin-interface"&gt;
&lt;h2&gt;The Rust-C plugin interface&lt;/h2&gt;
&lt;p&gt;The Rust code is contained in one source file, &lt;a class="reference external" href="https://github.com/kmdouglass/rust-libloading-example/blob/master/src/main.rs"&gt;src/main.rs&lt;/a&gt;. The design pattern contained within
consists of three kinds of objects:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;type definitions for the functions in the C library&lt;/li&gt;
&lt;li&gt;a &lt;tt class="docutils literal"&gt;VTable&lt;/tt&gt; struct that holds the external function types&lt;/li&gt;
&lt;li&gt;a &lt;tt class="docutils literal"&gt;Plugin&lt;/tt&gt; struct that holds the plugin's library, the &lt;tt class="docutils literal"&gt;VTable&lt;/tt&gt;, and a raw pointer to the
object provided by the C library&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let's take a look at each of these abstractions.&lt;/p&gt;
&lt;div class="section" id="external-function-types"&gt;
&lt;h3&gt;External function types&lt;/h3&gt;
&lt;p&gt;The external function types are defined as follows:&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_05f70e3bb46b417f86fb106c3524eed4-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#[repr(C)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_05f70e3bb46b417f86fb106c3524eed4-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_05f70e3bb46b417f86fb106c3524eed4-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_private&lt;/span&gt;: &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_05f70e3bb46b417f86fb106c3524eed4-4"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_05f70e3bb46b417f86fb106c3524eed4-5"&gt;&lt;/a&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;FreeObject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"C"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_05f70e3bb46b417f86fb106c3524eed4-6"&gt;&lt;/a&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Init&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"C"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_05f70e3bb46b417f86fb106c3524eed4-7"&gt;&lt;/a&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;GetApiVersion&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"C"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;c_int&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_05f70e3bb46b417f86fb106c3524eed4-8"&gt;&lt;/a&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;GetInfo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"C"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;c_int&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_05f70e3bb46b417f86fb106c3524eed4-9"&gt;&lt;/a&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;SetInfo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"C"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_int&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The opaque struct from the C library is represented as rust &lt;tt class="docutils literal"&gt;struct&lt;/tt&gt; with a single, private field
containing an empty array. &lt;a class="reference external" href="https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs"&gt;This is currently the recommended way&lt;/a&gt; to represent opaque structs in
the Rust FFI. Following the &lt;tt class="docutils literal"&gt;struct&lt;/tt&gt; definition are the type definitions for the foreign
functions.&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_4106bf0f510f4ff7b584fb5f36d30624-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;FreeObject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"C"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_4106bf0f510f4ff7b584fb5f36d30624-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Init&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"C"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_4106bf0f510f4ff7b584fb5f36d30624-3"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;For example, the &lt;tt class="docutils literal"&gt;Init&lt;/tt&gt; type represents a foreign C function that takes no arguments and returns
a mutable raw pointer to an &lt;tt class="docutils literal"&gt;Object&lt;/tt&gt; instance. This function type therefore represents the
&lt;tt class="docutils literal"&gt;Object&lt;/tt&gt; constructor in Rust.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-vtable"&gt;
&lt;h3&gt;The VTable&lt;/h3&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;VTable&lt;/tt&gt; serves as a way to collect the types associated with the C library functions into
one place. Furthermore, I added a version number to make it &lt;tt class="docutils literal"&gt;VTableV0&lt;/tt&gt;. The purpose in doing this
is to easily maintain backwards compatability with and follow changes to the C API.&lt;/p&gt;
&lt;p&gt;By looking at its definition, you can see that it contains a few &lt;tt class="docutils literal"&gt;RawSymbol&lt;/tt&gt; instances:&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_b183cd639bf6453ea1fc1995ab8211ef-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;VTableV0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_b183cd639bf6453ea1fc1995ab8211ef-2"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;free_object&lt;/span&gt;: &lt;span class="nc"&gt;RawSymbol&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FreeObject&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_b183cd639bf6453ea1fc1995ab8211ef-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;get_info&lt;/span&gt;: &lt;span class="nc"&gt;RawSymbol&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GetInfo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_b183cd639bf6453ea1fc1995ab8211ef-4"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;set_info&lt;/span&gt;: &lt;span class="nc"&gt;RawSymbol&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SetInfo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_b183cd639bf6453ea1fc1995ab8211ef-5"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;A &lt;tt class="docutils literal"&gt;RawSymbol&lt;/tt&gt; is a name that I gave to Unix-specific symbols from the &lt;tt class="docutils literal"&gt;libloading&lt;/tt&gt; Rust
library. (See the &lt;tt class="docutils literal"&gt;use&lt;/tt&gt; statements at the top of the source code file.) I am not storing plain
&lt;tt class="docutils literal"&gt;Symbols&lt;/tt&gt; from that library inside the VTable because the lifetime constraints associated with
plain &lt;tt class="docutils literal"&gt;Symbols&lt;/tt&gt; and their corresponding &lt;tt class="docutils literal"&gt;Library&lt;/tt&gt; do not allow me to take ownership of them
inside the struct. (You can find a few attempts in the commit history of this repository where I
tried to own plain &lt;tt class="docutils literal"&gt;Symbols&lt;/tt&gt;; none of these attempts would compile.)&lt;/p&gt;
&lt;p&gt;Instead, if I had used a plain &lt;tt class="docutils literal"&gt;Symbol&lt;/tt&gt;, then I would have had to lookup the symbols inside the C
library each time that I wanted to call them.&lt;/p&gt;
&lt;p&gt;The way to obtain &lt;tt class="docutils literal"&gt;RawSymbols&lt;/tt&gt; is to use the &lt;tt class="docutils literal"&gt;into_raw&lt;/tt&gt; method of a plain &lt;tt class="docutils literal"&gt;Symbol&lt;/tt&gt;. You can
find an example of this inside the &lt;tt class="docutils literal"&gt;VTable&lt;/tt&gt;'s constructor:&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_7af1db91e6a04513b398a87ea82ca3f1-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;Library&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;VTableV0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_7af1db91e6a04513b398a87ea82ca3f1-2"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Loading API version 0..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_7af1db91e6a04513b398a87ea82ca3f1-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free_object&lt;/span&gt;: &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FreeObject&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;b"free_object&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_7af1db91e6a04513b398a87ea82ca3f1-4"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free_object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free_object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;into_raw&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_7af1db91e6a04513b398a87ea82ca3f1-5"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;First, the &lt;tt class="docutils literal"&gt;free_object&lt;/tt&gt; &lt;tt class="docutils literal"&gt;Symbol&lt;/tt&gt; is imported from the library using the &lt;tt class="docutils literal"&gt;get()&lt;/tt&gt; method from
the library, then it is converted to a &lt;tt class="docutils literal"&gt;RawSymbol&lt;/tt&gt; in the following line so that it can be stored
inside the &lt;tt class="docutils literal"&gt;VTableV0&lt;/tt&gt; struct that is returned by the constructor. The whole function is marked as
&lt;tt class="docutils literal"&gt;unsafe&lt;/tt&gt; because of the multiple calls to the &lt;tt class="docutils literal"&gt;get&lt;/tt&gt; method.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-plugin"&gt;
&lt;h3&gt;The Plugin&lt;/h3&gt;
&lt;p&gt;Finally we reach the top of the hierarchy of the components that comprise this design, the
&lt;tt class="docutils literal"&gt;Plugin&lt;/tt&gt; struct. Its implementation follows:&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Plugin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-2"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;#[allow(dead_code)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;: &lt;span class="nc"&gt;Library&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-4"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-5"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;vtable&lt;/span&gt;: &lt;span class="nc"&gt;VTableV0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-6"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-7"&gt;&lt;/a&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-8"&gt;&lt;/a&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Plugin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-9"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;library_name&lt;/span&gt;: &lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nc"&gt;OsStr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="nc"&gt;Plugin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-10"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Library&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;library_name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-11"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;get_api_version&lt;/span&gt;: &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GetApiVersion&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;b"get_api_version&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-12"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vtable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;get_api_version&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-13"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VTableV0&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-14"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;panic&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unrecognized C API version number."&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-15"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-16"&gt;&lt;/a&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-17"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;: &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Init&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;b"init&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-18"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-19"&gt;&lt;/a&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-20"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;Plugin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-21"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;: &lt;span class="nc"&gt;library&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-22"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;: &lt;span class="nc"&gt;object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-23"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;vtable&lt;/span&gt;: &lt;span class="nc"&gt;vtable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-24"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-25"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-26"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-27"&gt;&lt;/a&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-28"&gt;&lt;/a&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Drop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Plugin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-29"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-30"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vtable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;free_object&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-31"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_a901913759eb4f36bb6ae1f61e1667e1-32"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The interesting parts here are the &lt;tt class="docutils literal"&gt;Plugin&lt;/tt&gt;'s constructor &lt;tt class="docutils literal"&gt;new&lt;/tt&gt; and the implementation of the
&lt;tt class="docutils literal"&gt;Drop&lt;/tt&gt; trait. After loading the library, the constructor calls the C library function that
returns its API version; if the version matches one for which we have a &lt;tt class="docutils literal"&gt;VTable&lt;/tt&gt;, then we create
the new &lt;tt class="docutils literal"&gt;VTable&lt;/tt&gt;. Next, we instantiate an &lt;tt class="docutils literal"&gt;Object&lt;/tt&gt; by calling its constructor to obtain a raw
pointer to it.&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_3b30d939dcb94bf5b21f9a3e5c261d24-1"&gt;&lt;/a&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;: &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Init&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;b"init&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_3b30d939dcb94bf5b21f9a3e5c261d24-2"&gt;&lt;/a&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The constructor packs the library, the &lt;tt class="docutils literal"&gt;VTable&lt;/tt&gt;, and the object pointer into a new &lt;tt class="docutils literal"&gt;Plugin&lt;/tt&gt;
struct and returns it.&lt;/p&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;Drop&lt;/tt&gt; trait implementation is used to automatically free the memory that has been allocated
when the pointer held by the &lt;tt class="docutils literal"&gt;Plugin&lt;/tt&gt; struct goes out-of-scope. It does this by calling the
&lt;tt class="docutils literal"&gt;free_object&lt;/tt&gt; method in the VTable.&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_196c66d6af1f4becae51d4f8eaa00883-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Drop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Plugin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_196c66d6af1f4becae51d4f8eaa00883-2"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_196c66d6af1f4becae51d4f8eaa00883-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vtable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;free_object&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_196c66d6af1f4becae51d4f8eaa00883-4"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_196c66d6af1f4becae51d4f8eaa00883-5"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="running-the-example"&gt;
&lt;h3&gt;Running the example&lt;/h3&gt;
&lt;p&gt;To run the example, run the following commands from the root directory of the example repository.&lt;/p&gt;
&lt;pre class="code console"&gt;&lt;a name="rest_code_60bbc661a2b749749e78afdcefd84448-1"&gt;&lt;/a&gt;&lt;span class="gp"&gt;$&lt;/span&gt; cargo build
&lt;a name="rest_code_60bbc661a2b749749e78afdcefd84448-2"&gt;&lt;/a&gt;&lt;span class="go"&gt;Compiling rust-libloading v0.1.0 (/home/kmdouglass/src/rust-libloading-example)&lt;/span&gt;
&lt;a name="rest_code_60bbc661a2b749749e78afdcefd84448-3"&gt;&lt;/a&gt;&lt;span class="go"&gt; Finished dev [unoptimized + debuginfo] target(s) in 0.27s&lt;/span&gt;
&lt;a name="rest_code_60bbc661a2b749749e78afdcefd84448-4"&gt;&lt;/a&gt;&lt;span class="gp"&gt;$&lt;/span&gt; cargo run
&lt;a name="rest_code_60bbc661a2b749749e78afdcefd84448-5"&gt;&lt;/a&gt;&lt;span class="go"&gt; Finished dev [unoptimized + debuginfo] target(s) in 0.01s&lt;/span&gt;
&lt;a name="rest_code_60bbc661a2b749749e78afdcefd84448-6"&gt;&lt;/a&gt;&lt;span class="go"&gt;  Running `target/debug/rust-libloading`&lt;/span&gt;
&lt;a name="rest_code_60bbc661a2b749749e78afdcefd84448-7"&gt;&lt;/a&gt;&lt;span class="go"&gt;Loading API version 0...&lt;/span&gt;
&lt;a name="rest_code_60bbc661a2b749749e78afdcefd84448-8"&gt;&lt;/a&gt;&lt;span class="go"&gt;Original value: 0&lt;/span&gt;
&lt;a name="rest_code_60bbc661a2b749749e78afdcefd84448-9"&gt;&lt;/a&gt;&lt;span class="go"&gt;New value: 42&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The &lt;tt class="docutils literal"&gt;main&lt;/tt&gt; method of the Rust code creates the plugin, prints the default value of the data held
by the object (which is instantiated by the C library), and then mutates the data to the value
&lt;tt class="docutils literal"&gt;42&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;It then prints this value, demonstrating that the FFI calls work.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="discussion"&gt;
&lt;h2&gt;Discussion&lt;/h2&gt;
&lt;p&gt;The most difficult part of developing this design was finding a way to own the symbols exposed by
the plugin library. For me, it was not completely evident from the &lt;a class="reference external" href="https://docs.rs/libloading/0.5.1/libloading/"&gt;libloading documentation&lt;/a&gt; that
this was the purpose of the &lt;tt class="docutils literal"&gt;into_raw&lt;/tt&gt; method on a &lt;tt class="docutils literal"&gt;Symbol&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;What I like about this design is that the whole plugin interface fits nicely within a simple
hierarchy with a collection of foreign method types at its base. It also supports changes to the C
API because a new &lt;tt class="docutils literal"&gt;VTable&lt;/tt&gt; can be created each time the API changes.&lt;/p&gt;
&lt;p&gt;One current disadvantage of the design is that &lt;tt class="docutils literal"&gt;free_object&lt;/tt&gt; is exposed through the VTable. I
think that this opens the possibility for a double-free error. One way to prevent this is to hide
the &lt;tt class="docutils literal"&gt;free_object&lt;/tt&gt; method, loading its corresponding symbol only when the &lt;tt class="docutils literal"&gt;drop&lt;/tt&gt; method is
called.&lt;/p&gt;
&lt;p&gt;Another disadvantage of this design is that it relies on the particular C API exposed by the
library. C programmers have a large amount of freedom in designing APIs for their libraries. They
are not forced to use opaque structs or to version their APIs. As a result, I don't believe that
the plugin design presented here can be completely generalized to any C library.&lt;/p&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;Plugin&lt;/tt&gt; struct is almost certainly not thread safe. To make it thread safe, it may be
necessary to wrap the raw pointer in a &lt;tt class="docutils literal"&gt;Mutex&lt;/tt&gt;. It may even be simpler to wrap the entire struct
in a &lt;tt class="docutils literal"&gt;Mutex&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Finally, owning raw symbols is not platform independent. You can see at the top of the Rust source
code that I am importing the &lt;tt class="docutils literal"&gt;Symbol&lt;/tt&gt; object specific to UNIX systems. One would need to change
this if it was intended to work on Windows.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="summary"&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;I presented a design pattern for managing C-language plugins in Rust.&lt;/li&gt;
&lt;li&gt;The design pattern consists of a collection of foreign object function types, the
&lt;tt class="docutils literal"&gt;VTable&lt;/tt&gt;. This collection is part of a larger collection which owns pointers to the opaque data
types exposed by the library, as well as the plugin library itself.&lt;/li&gt;
&lt;li&gt;The trick to owning symbols (instead of looking them up in the library each time you want to use
them), is to use &lt;tt class="docutils literal"&gt;into_raw&lt;/tt&gt; method that is implemented on libloading's &lt;tt class="docutils literal"&gt;Symbol&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;This design cannot be completely generalized to any C library, but should provide a good starting
point to work with FFI plugins in Rust.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/div&gt;</description><category>c</category><category>rust</category><guid>http://kmdouglass.github.io/posts/a-simple-plugin-interface-for-the-rust-ffi/</guid><pubDate>Sun, 16 Jun 2019 07:33:33 GMT</pubDate></item><item><title>Complex data types and the Rust FFI</title><link>http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/</link><dc:creator>Kyle M. Douglass</dc:creator><description>&lt;div&gt;&lt;p&gt;The &lt;a class="reference external" href="https://doc.rust-lang.org/nomicon/ffi.html"&gt;Rust Foreign Function Interface&lt;/a&gt; (FFI, for short) is a feature of Rust that enables the
sharing of data and functions between parts of code that have been written in different
languages. I am interested in the FFI because many libraries used in embedded systems are written
in C, and I would like to leverage them for my embedded work with Rust.&lt;/p&gt;
&lt;p&gt;I quickly learned from my initial experiments with the Rust FFI that one of its challenges is
casting data types into a form that may be consumed by other languages. This challenge is not
unique to the Rust FFI, and there are numerous reasons for it. For one, different languages use
different mechanisms to layout data in the computer's memory. What's more, names for functions and
data types are often mangled, which means that the symbol in a library that maps to a function may
be different than the name that you give to the function in your code. As far as I know, C
compilers do not mangle symbol names, and partly for this reason the C language is often used as an
intermediary language in FFIs. Converting Rust to C is therefore an important skill when using Rust
for multi-language work.&lt;/p&gt;
&lt;p&gt;There are a few good resources on the internet about using the Rust FFI to expose functions written
in Rust to other languages. However, I found little information about passing data types between
languages. To help remedy this situation, I describe in this post a simple Rust library that I
wrote to explore how to pass complex data types from Rust to C.&lt;/p&gt;
&lt;div class="section" id="an-example-ffi-project"&gt;
&lt;h2&gt;An example FFI project&lt;/h2&gt;
&lt;p&gt;I created the Rust library in the typical way by first starting a new project with Cargo:&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_372b84d1c7254bbaa80260de2378dbce-1"&gt;&lt;/a&gt;$ cargo new --lib rstruct
&lt;a name="rest_code_372b84d1c7254bbaa80260de2378dbce-2"&gt;&lt;/a&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; rstruct
&lt;/pre&gt;&lt;p&gt;Inside, I modified the contents of &lt;tt class="docutils literal"&gt;Cargo.toml&lt;/tt&gt; to the following:&lt;/p&gt;
&lt;pre class="code text"&gt;&lt;a name="rest_code_5fbba1c3a9fd47cd91f5cd370105ecf6-1"&gt;&lt;/a&gt;[package]
&lt;a name="rest_code_5fbba1c3a9fd47cd91f5cd370105ecf6-2"&gt;&lt;/a&gt;name = "rstruct"
&lt;a name="rest_code_5fbba1c3a9fd47cd91f5cd370105ecf6-3"&gt;&lt;/a&gt;version = "0.1.0"
&lt;a name="rest_code_5fbba1c3a9fd47cd91f5cd370105ecf6-4"&gt;&lt;/a&gt;authors = ["Kyle M. Douglass"]
&lt;a name="rest_code_5fbba1c3a9fd47cd91f5cd370105ecf6-5"&gt;&lt;/a&gt;edition = "2018"
&lt;a name="rest_code_5fbba1c3a9fd47cd91f5cd370105ecf6-6"&gt;&lt;/a&gt;
&lt;a name="rest_code_5fbba1c3a9fd47cd91f5cd370105ecf6-7"&gt;&lt;/a&gt;[lib]
&lt;a name="rest_code_5fbba1c3a9fd47cd91f5cd370105ecf6-8"&gt;&lt;/a&gt;crate-type = ["cdylib"]
&lt;a name="rest_code_5fbba1c3a9fd47cd91f5cd370105ecf6-9"&gt;&lt;/a&gt;
&lt;a name="rest_code_5fbba1c3a9fd47cd91f5cd370105ecf6-10"&gt;&lt;/a&gt;[dependencies]
&lt;/pre&gt;&lt;p&gt;The only lines that I added were &lt;tt class="docutils literal"&gt;[lib]&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;crate-type&lt;/span&gt; = ["cdylib"]&lt;/tt&gt;. As described in the
&lt;a class="reference external" href="https://doc.rust-lang.org/edition-guide/rust-2018/platform-and-target-support/cdylib-crates-for-c-interoperability.html"&gt;2018 edition guide&lt;/a&gt;, this type of crate produces a binary that has no Rust-specific information
in it and is intended for use through a C FFI.&lt;/p&gt;
&lt;p&gt;Next, I opened the &lt;tt class="docutils literal"&gt;src/lib.rs&lt;/tt&gt; source file, removed the auto-generated content, and added the
following source.&lt;/p&gt;
&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-1"&gt; 1&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-2"&gt; 2&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-3"&gt; 3&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-4"&gt; 4&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-5"&gt; 5&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-6"&gt; 6&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-7"&gt; 7&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-8"&gt; 8&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-9"&gt; 9&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-10"&gt;10&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-11"&gt;11&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-12"&gt;12&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-13"&gt;13&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-14"&gt;14&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-15"&gt;15&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-16"&gt;16&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-17"&gt;17&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-18"&gt;18&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-19"&gt;19&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-20"&gt;20&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-21"&gt;21&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-22"&gt;22&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-23"&gt;23&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-24"&gt;24&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-25"&gt;25&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-26"&gt;26&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-27"&gt;27&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-28"&gt;28&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-29"&gt;29&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-30"&gt;30&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-31"&gt;31&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-32"&gt;32&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-33"&gt;33&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-34"&gt;34&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-35"&gt;35&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-36"&gt;36&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_d724c2d6c3244a979b169b4a559585b7-37"&gt;37&lt;/a&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="code rust"&gt;&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;::&lt;span class="n"&gt;boxed&lt;/span&gt;::&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;::&lt;span class="n"&gt;ffi&lt;/span&gt;::&lt;span class="n"&gt;CString&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-3"&gt;&lt;/a&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;::&lt;span class="n"&gt;os&lt;/span&gt;::&lt;span class="n"&gt;raw&lt;/span&gt;::&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-4"&gt;&lt;/a&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-5"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#[repr(C)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-6"&gt;&lt;/a&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;RStruct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-7"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-8"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;: &lt;span class="nc"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-9"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-10"&gt;&lt;/a&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-11"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#[repr(C)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-12"&gt;&lt;/a&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-13"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-14"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_Float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-15"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-16"&gt;&lt;/a&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-17"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-18"&gt;&lt;/a&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"C"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;data_new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RStruct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-19"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Inside data_new()."&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-20"&gt;&lt;/a&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-21"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;::&lt;span class="n"&gt;into_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RStruct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-22"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;: &lt;span class="nc"&gt;CString&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"my_rstruct"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-23"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error: CString::new()"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-24"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;into_raw&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-25"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;: &lt;span class="nc"&gt;Value&lt;/span&gt;::&lt;span class="n"&gt;_Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-26"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-27"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-28"&gt;&lt;/a&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-29"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-30"&gt;&lt;/a&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"C"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;data_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RStruct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-31"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_null&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-32"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-33"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-34"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-35"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;::&lt;span class="n"&gt;from_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-36"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_d724c2d6c3244a979b169b4a559585b7-37"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;Roughly speaking, this simple library does two things. First, it defines two data types, a struct
called &lt;tt class="docutils literal"&gt;RStruct&lt;/tt&gt; and a Rust enum (not to be confused with a C enum!) called &lt;tt class="docutils literal"&gt;Value&lt;/tt&gt;. Second, it
exposes two functions that may be used to access instances of these data types from C:
&lt;tt class="docutils literal"&gt;data_new()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;data_free()&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Let's take closer look now at what the code is doing.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="defining-structs-and-enums-for-use-in-c"&gt;
&lt;h2&gt;Defining structs and enums for use in C&lt;/h2&gt;
&lt;p&gt;I want to expose instances of the RStruct type to C code. The definition of &lt;tt class="docutils literal"&gt;RStruct&lt;/tt&gt; is&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_1b6b309db3de40e3b9da5e9c3a097dbf-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#[repr(C)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_1b6b309db3de40e3b9da5e9c3a097dbf-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;RStruct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_1b6b309db3de40e3b9da5e9c3a097dbf-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c_char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_1b6b309db3de40e3b9da5e9c3a097dbf-4"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;: &lt;span class="nc"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_1b6b309db3de40e3b9da5e9c3a097dbf-5"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The first line here is &lt;tt class="docutils literal"&gt;[repr(C)]&lt;/tt&gt;. This is an attribute that modifies the layout of the struct
in memory to "do what C does." As described in the &lt;a class="reference external" href="https://doc.rust-lang.org/nomicon/other-reprs.html"&gt;Rustonomicon&lt;/a&gt;,&lt;/p&gt;
&lt;blockquote&gt;
The order, size, and alignment of fields is exactly what you would expect from C or C++. Any
type you expect to pass through an FFI boundary should have repr(C), as C is the lingua-franca
of the programming world.&lt;/blockquote&gt;
&lt;p&gt;Next, we define a public struct just as we would if we were writing typical Rust code. In this
example, the struct has two fields. The first is a field called &lt;tt class="docutils literal"&gt;name&lt;/tt&gt;, which has a type &lt;tt class="docutils literal"&gt;*const
c_char&lt;/tt&gt;. The Rust data types &lt;tt class="docutils literal"&gt;String&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&amp;amp;str&lt;/tt&gt; cannot be interpreted in C, so instead we
define the data type as a &lt;a class="reference external" href="https://doc.rust-lang.org/std/primitive.pointer.html"&gt;raw pointer&lt;/a&gt; to a &lt;tt class="docutils literal"&gt;c_char&lt;/tt&gt;. (In this case, &lt;tt class="docutils literal"&gt;*&lt;/tt&gt; is not dereferencing
the pointer but is &lt;a class="reference external" href="https://doc.rust-lang.org/beta/book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer"&gt;part of the type name&lt;/a&gt; &lt;tt class="docutils literal"&gt;*const T&lt;/tt&gt;.)&lt;/p&gt;
&lt;p&gt;The second field is an enum whose definition follows:&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_50968308faa5491b9ed28adbef50b95c-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#[repr(C)]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_50968308faa5491b9ed28adbef50b95c-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_50968308faa5491b9ed28adbef50b95c-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_50968308faa5491b9ed28adbef50b95c-4"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;_Float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_50968308faa5491b9ed28adbef50b95c-5"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Again we use &lt;tt class="docutils literal"&gt;#[repr(C)]&lt;/tt&gt; to indicate that we want the enum to be laid out in memory in the same
manner as in C. The enum &lt;tt class="docutils literal"&gt;Value&lt;/tt&gt; has two variants, &lt;tt class="docutils literal"&gt;_Int&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;_Float&lt;/tt&gt;, that each contain a
value of &lt;tt class="docutils literal"&gt;i32&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;f64&lt;/tt&gt;, respectively. If you're familiar with C, then you may have already
noticed that C enums are differnt from Rust enums in that they do not hold any data themselves. How
this minor annoyance is solved will be seen later when we generate the C header for this library.&lt;/p&gt;
&lt;p&gt;The data types i32 and f64 are easily translated into C's equivalent numeric data types, so there
is no need to do anything special with them.&lt;/p&gt;
&lt;div class="section" id="instantiating-and-freeing-memory"&gt;
&lt;h3&gt;Instantiating and freeing Memory&lt;/h3&gt;
&lt;p&gt;Following the data type definitions, there are two functions that are exposed through the FFI
boundary, one for instantiating an &lt;tt class="docutils literal"&gt;RStruct&lt;/tt&gt; and one for freeing the memory associated with an
&lt;tt class="docutils literal"&gt;RStruct&lt;/tt&gt;. The method for instantiation is first:&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_c5c45d679080471fa4e88d3ba112337f-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_c5c45d679080471fa4e88d3ba112337f-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"C"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;data_new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&amp;gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RStruct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_c5c45d679080471fa4e88d3ba112337f-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Inside data_new()."&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_c5c45d679080471fa4e88d3ba112337f-4"&gt;&lt;/a&gt;
&lt;a name="rest_code_c5c45d679080471fa4e88d3ba112337f-5"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;::&lt;span class="n"&gt;into_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RStruct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_c5c45d679080471fa4e88d3ba112337f-6"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;: &lt;span class="nc"&gt;CString&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"my_rstruct"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_c5c45d679080471fa4e88d3ba112337f-7"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error: CString::new()"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_c5c45d679080471fa4e88d3ba112337f-8"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;into_raw&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_c5c45d679080471fa4e88d3ba112337f-9"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;: &lt;span class="nc"&gt;Value&lt;/span&gt;::&lt;span class="n"&gt;_Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_c5c45d679080471fa4e88d3ba112337f-10"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_c5c45d679080471fa4e88d3ba112337f-11"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The first line contains an attribute called &lt;tt class="docutils literal"&gt;#[no_mangle]&lt;/tt&gt;. As defined in &lt;a class="reference external" href="https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html#calling-rust-functions-from-other-languages"&gt;the Book&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
Mangling is when a compiler changes the name we’ve given a function to a different name that
contains more information for other parts of the compilation process to consume but is less
human readable.&lt;/blockquote&gt;
&lt;p&gt;Placing the &lt;tt class="docutils literal"&gt;#[no_mangle]&lt;/tt&gt; attribute before the function definition ensures that the function
name matches that of the corresponding symbol in the library.&lt;/p&gt;
&lt;p&gt;Next is the function definition &lt;tt class="docutils literal"&gt;pub extern "C" fn data_new() &lt;span class="pre"&gt;-&amp;gt;&lt;/span&gt; *mut RStruct&lt;/tt&gt;. Let's break this
down into parts to understand it better:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;pub&lt;/tt&gt; : The function will be callable from outside the library&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;extern "C"&lt;/tt&gt; : This line serves two different purposes in Rust, both related to FFI. In my
case, I use it specify that the function should be exposed with the &lt;a class="reference external" href="https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code"&gt;application binary interface
from C&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;fn data_new()&lt;/tt&gt; : This is just the usual &lt;tt class="docutils literal"&gt;fn&lt;/tt&gt; keyword and the name of the function&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-&amp;gt;&lt;/span&gt; *mut RStruct&lt;/tt&gt; : Here I specify that the function will return a mutable, raw pointer to an
&lt;tt class="docutils literal"&gt;RStruct instance&lt;/tt&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The purpose of this function is to create a &lt;tt class="docutils literal"&gt;RStruct&lt;/tt&gt; instance and return a pointer to it. The
&lt;tt class="docutils literal"&gt;RStruct&lt;/tt&gt; is created just as we would any other struct in Rust, with the exception of the
&lt;tt class="docutils literal"&gt;name&lt;/tt&gt; field:&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_db22fa28688d448aa57c1b463f3b296e-1"&gt;&lt;/a&gt;&lt;span class="n"&gt;RStruct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_db22fa28688d448aa57c1b463f3b296e-2"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;: &lt;span class="nc"&gt;CString&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"my_rstruct"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_db22fa28688d448aa57c1b463f3b296e-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error: CString::new()"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_db22fa28688d448aa57c1b463f3b296e-4"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;into_raw&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_db22fa28688d448aa57c1b463f3b296e-5"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;: &lt;span class="nc"&gt;Value&lt;/span&gt;::&lt;span class="n"&gt;_Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_db22fa28688d448aa57c1b463f3b296e-6"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The &lt;tt class="docutils literal"&gt;CString&lt;/tt&gt; is first created with the &lt;tt class="docutils literal"&gt;new()&lt;/tt&gt; constructor and contains the value
&lt;tt class="docutils literal"&gt;"my_rstruct"&lt;/tt&gt;. After unpacking the result with &lt;tt class="docutils literal"&gt;expect()&lt;/tt&gt;, I call the &lt;tt class="docutils literal"&gt;into_raw()&lt;/tt&gt; method to
create a raw pointer to the C string whose &lt;a class="reference external" href="https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_raw"&gt;ownership will be passed off to the calling C
code&lt;/a&gt;. (If I had used &lt;tt class="docutils literal"&gt;as_ptr()&lt;/tt&gt; instead, the pointer would have been dropped immediately after
the function call because the &lt;tt class="docutils literal"&gt;CString&lt;/tt&gt; &lt;a class="reference external" href="https://doc.rust-lang.org/std/ffi/struct.CString.html#method.as_ptr"&gt;would have been deallocated&lt;/a&gt;.) The &lt;tt class="docutils literal"&gt;value&lt;/tt&gt; field is
instantiated as it would be in normal Rust.&lt;/p&gt;
&lt;p&gt;What is perhaps new in this method is the &lt;tt class="docutils literal"&gt;Box&lt;/tt&gt; type that wraps the &lt;tt class="docutils literal"&gt;RStruct&lt;/tt&gt; instance.&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_23022038f17b42e8a9a6086151a67fda-1"&gt;&lt;/a&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;::&lt;span class="n"&gt;into_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;A &lt;tt class="docutils literal"&gt;Box&lt;/tt&gt; is one of Rust's smart pointers that is used to &lt;a class="reference external" href="https://doc.rust-lang.org/book/ch15-01-box.html"&gt;allocate memory for a data type on the
heap&lt;/a&gt;. When &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Box::new()&lt;/span&gt;&lt;/tt&gt; is called it creates a pointer to the newly created &lt;tt class="docutils literal"&gt;RStruct&lt;/tt&gt;
instance. Normally, this pointer would be dropped and the memory automatically deallocated when the
&lt;tt class="docutils literal"&gt;data_new()&lt;/tt&gt; function returns. However, the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Box::into_raw()&lt;/span&gt;&lt;/tt&gt; function serves the same purpose
here as the corresponding function for &lt;tt class="docutils literal"&gt;CString&lt;/tt&gt;: it hands off ownership of the pointer to the
calling code so that the memory is not deallocated.&lt;/p&gt;
&lt;p&gt;There is a rule-of-thumb that memory allocated by Rust should be freed by Rust. For this reason, we
provide the &lt;tt class="docutils literal"&gt;data_free()&lt;/tt&gt; method that C code may use to deallocate the memory that is allocated
by &lt;tt class="docutils literal"&gt;data_new()&lt;/tt&gt;.&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_1afd7c46e2284749bb2edc66c6b7c732-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#[no_mangle]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_1afd7c46e2284749bb2edc66c6b7c732-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;extern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"C"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;data_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;: &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;RStruct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_1afd7c46e2284749bb2edc66c6b7c732-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_null&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_1afd7c46e2284749bb2edc66c6b7c732-4"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_1afd7c46e2284749bb2edc66c6b7c732-5"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_1afd7c46e2284749bb2edc66c6b7c732-6"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_1afd7c46e2284749bb2edc66c6b7c732-7"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;::&lt;span class="n"&gt;from_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_1afd7c46e2284749bb2edc66c6b7c732-8"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_1afd7c46e2284749bb2edc66c6b7c732-9"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;This function accepts a mutable pointer to an RStruct. First, it checks whether the pointer is null
and if it is, the function returns without doing anything. Assuming that the pointer is not null,
the &lt;tt class="docutils literal"&gt;Box&lt;/tt&gt; is reconstructed from it inside an &lt;tt class="docutils literal"&gt;unsafe&lt;/tt&gt; block because &lt;tt class="docutils literal"&gt;from_raw()&lt;/tt&gt; &lt;a class="reference external" href="https://doc.rust-lang.org/std/boxed/struct.Box.html#method.from_raw"&gt;is
unsafe&lt;/a&gt;. Importantly, this new Box pointer will go out of scope at the end of the function so that
it will automatically be dropped when the function returns.&lt;/p&gt;
&lt;p&gt;Building the library is simple. I run &lt;tt class="docutils literal"&gt;cargo build &lt;span class="pre"&gt;--release&lt;/span&gt;&lt;/tt&gt; to build a release version. The
library itself will be found at &lt;tt class="docutils literal"&gt;target/release/librstruct.so&lt;/tt&gt;. On Linux, one can verify that it
contains the &lt;tt class="docutils literal"&gt;data_new()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;data_free()&lt;/tt&gt; methods by displaying its symbols with the &lt;tt class="docutils literal"&gt;nm
&lt;span class="pre"&gt;-g&lt;/span&gt;&lt;/tt&gt; command:&lt;/p&gt;
&lt;pre class="code console"&gt;&lt;a name="rest_code_a6e2baa52ded42a6a1932c5ec125de45-1"&gt;&lt;/a&gt;&lt;span class="gp"&gt;$&lt;/span&gt; nm -g target/release/librstruct.so
&lt;a name="rest_code_a6e2baa52ded42a6a1932c5ec125de45-2"&gt;&lt;/a&gt;&lt;span class="gp"&gt;#&lt;/span&gt; snip
&lt;a name="rest_code_a6e2baa52ded42a6a1932c5ec125de45-3"&gt;&lt;/a&gt;&lt;span class="go"&gt;00000000000046c0 T data_free&lt;/span&gt;
&lt;a name="rest_code_a6e2baa52ded42a6a1932c5ec125de45-4"&gt;&lt;/a&gt;&lt;span class="go"&gt;00000000000044e0 T data_new&lt;/span&gt;
&lt;a name="rest_code_a6e2baa52ded42a6a1932c5ec125de45-5"&gt;&lt;/a&gt;&lt;span class="gp"&gt;#&lt;/span&gt; snip
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="generating-the-header-for-the-library"&gt;
&lt;h3&gt;Generating the header for the library&lt;/h3&gt;
&lt;p&gt;Now that I have a shared library, I want to access the functions that it exposes from C. To do
this, I first need a header file that I can use to import the library's declarations into the C
code. Moreover, generating the header can help in understanding how Rust translates its data types
to C.&lt;/p&gt;
&lt;p&gt;I will use &lt;a class="reference external" href="https://github.com/eqrion/cbindgen"&gt;cbindgen&lt;/a&gt; to automatically generate the header. &lt;tt class="docutils literal"&gt;cbindgen&lt;/tt&gt; is installed with the
command&lt;/p&gt;
&lt;pre class="code console"&gt;&lt;a name="rest_code_ac72fd56120b497b9d8d1c1be7dbf49e-1"&gt;&lt;/a&gt;&lt;span class="gp"&gt;$&lt;/span&gt; cargo install cbindgen
&lt;/pre&gt;&lt;p&gt;&lt;tt class="docutils literal"&gt;cbindgen&lt;/tt&gt; is highly configurable, but for the project described here I only need its most basic
functionality. Assuming that I am in the root directory of my Rust project, I generate the header
&lt;tt class="docutils literal"&gt;rstruct.h&lt;/tt&gt; with the following&lt;/p&gt;
&lt;pre class="code console"&gt;&lt;a name="rest_code_dabad64b9038496cba08a30fc4e7f836-1"&gt;&lt;/a&gt;&lt;span class="gp"&gt;$&lt;/span&gt; cbindgen --lang C -o rstruct.h .
&lt;/pre&gt;&lt;p&gt;After running &lt;tt class="docutils literal"&gt;cbindgen&lt;/tt&gt; there is a new file called &lt;tt class="docutils literal"&gt;rstruct.h&lt;/tt&gt; in the project folder. Here are
its contents:&lt;/p&gt;
&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-1"&gt; 1&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-2"&gt; 2&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-3"&gt; 3&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-4"&gt; 4&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-5"&gt; 5&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-6"&gt; 6&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-7"&gt; 7&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-8"&gt; 8&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-9"&gt; 9&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-10"&gt;10&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-11"&gt;11&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-12"&gt;12&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-13"&gt;13&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-14"&gt;14&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-15"&gt;15&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-16"&gt;16&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-17"&gt;17&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-18"&gt;18&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-19"&gt;19&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-20"&gt;20&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-21"&gt;21&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-22"&gt;22&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-23"&gt;23&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-24"&gt;24&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-25"&gt;25&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-26"&gt;26&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-27"&gt;27&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-28"&gt;28&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-29"&gt;29&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-30"&gt;30&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-31"&gt;31&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-32"&gt;32&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-33"&gt;33&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_b88b49909bea49c7a9bf9730597ecdd9-34"&gt;34&lt;/a&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="code c"&gt;&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdarg.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-2"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdbool.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-3"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdint.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-4"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-5"&gt;&lt;/a&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-6"&gt;&lt;/a&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-7"&gt;&lt;/a&gt;  &lt;span class="n"&gt;_Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-8"&gt;&lt;/a&gt;  &lt;span class="n"&gt;_Float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-9"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Value_Tag&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-10"&gt;&lt;/a&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-11"&gt;&lt;/a&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-12"&gt;&lt;/a&gt;  &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;_0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-13"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;_Int_Body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-14"&gt;&lt;/a&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-15"&gt;&lt;/a&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-16"&gt;&lt;/a&gt;  &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;_0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-17"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;_Float_Body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-18"&gt;&lt;/a&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-19"&gt;&lt;/a&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-20"&gt;&lt;/a&gt;  &lt;span class="n"&gt;Value_Tag&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-21"&gt;&lt;/a&gt;  &lt;span class="k"&gt;union&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-22"&gt;&lt;/a&gt;    &lt;span class="n"&gt;_Int_Body&lt;/span&gt; &lt;span class="n"&gt;_int&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-23"&gt;&lt;/a&gt;    &lt;span class="n"&gt;_Float_Body&lt;/span&gt; &lt;span class="n"&gt;_float&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-24"&gt;&lt;/a&gt;  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-25"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-26"&gt;&lt;/a&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-27"&gt;&lt;/a&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-28"&gt;&lt;/a&gt;  &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-29"&gt;&lt;/a&gt;  &lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-30"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;RStruct&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-31"&gt;&lt;/a&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-32"&gt;&lt;/a&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;data_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RStruct&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-33"&gt;&lt;/a&gt;
&lt;a name="rest_code_b88b49909bea49c7a9bf9730597ecdd9-34"&gt;&lt;/a&gt;&lt;span class="n"&gt;RStruct&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;data_new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;First, you can see the &lt;tt class="docutils literal"&gt;enum&lt;/tt&gt; that contains the variations of the &lt;tt class="docutils literal"&gt;Value&lt;/tt&gt; data type that is
stored in the &lt;tt class="docutils literal"&gt;RStruct&lt;/tt&gt; and that was defined in Rust. The name of this new type is &lt;tt class="docutils literal"&gt;Value_Tag&lt;/tt&gt;,
and it is used to define the current type of a value.&lt;/p&gt;
&lt;pre class="code c"&gt;&lt;a name="rest_code_1aaaccaac05d4839adbe9f7cff192874-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_1aaaccaac05d4839adbe9f7cff192874-2"&gt;&lt;/a&gt;  &lt;span class="n"&gt;Value_Tag&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_1aaaccaac05d4839adbe9f7cff192874-3"&gt;&lt;/a&gt;  &lt;span class="k"&gt;union&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_1aaaccaac05d4839adbe9f7cff192874-4"&gt;&lt;/a&gt;    &lt;span class="n"&gt;_Int_Body&lt;/span&gt; &lt;span class="n"&gt;_int&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_1aaaccaac05d4839adbe9f7cff192874-5"&gt;&lt;/a&gt;    &lt;span class="n"&gt;_Float_Body&lt;/span&gt; &lt;span class="n"&gt;_float&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_1aaaccaac05d4839adbe9f7cff192874-6"&gt;&lt;/a&gt;  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;a name="rest_code_1aaaccaac05d4839adbe9f7cff192874-7"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;A &lt;tt class="docutils literal"&gt;Value&lt;/tt&gt; is just another struct that contains a &lt;tt class="docutils literal"&gt;Value_Tag&lt;/tt&gt; field to identify which variant of
the &lt;tt class="docutils literal"&gt;enum&lt;/tt&gt; it is holding and a &lt;tt class="docutils literal"&gt;union&lt;/tt&gt; field that holds the actual value.&lt;/p&gt;
&lt;p&gt;The important thing to understand here is that &lt;tt class="docutils literal"&gt;cbindgen&lt;/tt&gt; effectively uses nested C data types to
represent complex Rust data structures. In particular, Rust &lt;tt class="docutils literal"&gt;enums&lt;/tt&gt; are a combination of C
&lt;tt class="docutils literal"&gt;structs&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;enums&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;unions&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="calling-the-library-from-c"&gt;
&lt;h2&gt;Calling the library from C&lt;/h2&gt;
&lt;p&gt;With everything in place, it's now time to write the C program. My example C program looks like the
following:&lt;/p&gt;
&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-1"&gt; 1&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-2"&gt; 2&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-3"&gt; 3&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-4"&gt; 4&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-5"&gt; 5&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-6"&gt; 6&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-7"&gt; 7&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-8"&gt; 8&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-9"&gt; 9&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-10"&gt;10&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-11"&gt;11&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-12"&gt;12&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-13"&gt;13&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-14"&gt;14&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-15"&gt;15&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-16"&gt;16&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-17"&gt;17&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-18"&gt;18&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-19"&gt;19&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-20"&gt;20&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-21"&gt;21&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-22"&gt;22&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-23"&gt;23&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-24"&gt;24&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-25"&gt;25&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-26"&gt;26&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-27"&gt;27&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-28"&gt;28&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-29"&gt;29&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-30"&gt;30&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-31"&gt;31&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-32"&gt;32&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-33"&gt;33&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-34"&gt;34&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-35"&gt;35&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-36"&gt;36&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-37"&gt;37&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-38"&gt;38&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-39"&gt;39&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-40"&gt;40&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-41"&gt;41&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-42"&gt;42&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-43"&gt;43&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-44"&gt;44&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-45"&gt;45&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-46"&gt;46&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-47"&gt;47&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-48"&gt;48&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-49"&gt;49&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-50"&gt;50&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-51"&gt;51&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-52"&gt;52&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/#rest_code_8334087a10e5400082a4f596ff8b5e4e-53"&gt;53&lt;/a&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="code c"&gt;&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;dlfcn.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-2"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-3"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-4"&gt;&lt;/a&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-5"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"rstruct.h"&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-6"&gt;&lt;/a&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-7"&gt;&lt;/a&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-8"&gt;&lt;/a&gt;  &lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-9"&gt;&lt;/a&gt;  &lt;span class="n"&gt;RStruct&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_new&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-10"&gt;&lt;/a&gt;  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_free&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;RStruct&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-11"&gt;&lt;/a&gt;  &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-12"&gt;&lt;/a&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-13"&gt;&lt;/a&gt;  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Loading librstruct.so...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-14"&gt;&lt;/a&gt;  &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-15"&gt;&lt;/a&gt;    &lt;span class="s"&gt;"librstruct.so"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-16"&gt;&lt;/a&gt;    &lt;span class="n"&gt;RTLD_LAZY&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-17"&gt;&lt;/a&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-18"&gt;&lt;/a&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-19"&gt;&lt;/a&gt;    &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dlerror&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-20"&gt;&lt;/a&gt;    &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXIT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-21"&gt;&lt;/a&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-22"&gt;&lt;/a&gt;  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Done.&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-23"&gt;&lt;/a&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-24"&gt;&lt;/a&gt;  &lt;span class="n"&gt;dlerror&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-25"&gt;&lt;/a&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-26"&gt;&lt;/a&gt;  &lt;span class="n"&gt;data_new&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RStruct&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="n"&gt;dlsym&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"data_new"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-27"&gt;&lt;/a&gt;  &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dlerror&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-28"&gt;&lt;/a&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-29"&gt;&lt;/a&gt;    &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-30"&gt;&lt;/a&gt;    &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXIT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-31"&gt;&lt;/a&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-32"&gt;&lt;/a&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-33"&gt;&lt;/a&gt;  &lt;span class="n"&gt;dlerror&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-34"&gt;&lt;/a&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-35"&gt;&lt;/a&gt;  &lt;span class="n"&gt;data_free&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;RStruct&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="n"&gt;dlsym&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"data_free"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-36"&gt;&lt;/a&gt;  &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dlerror&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-37"&gt;&lt;/a&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-38"&gt;&lt;/a&gt;    &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-39"&gt;&lt;/a&gt;    &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXIT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-40"&gt;&lt;/a&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-41"&gt;&lt;/a&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-42"&gt;&lt;/a&gt;  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Calling data_new() from main.c...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-43"&gt;&lt;/a&gt;  &lt;span class="n"&gt;RStruct&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_new&lt;/span&gt;&lt;span class="p"&gt;)();&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-44"&gt;&lt;/a&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-45"&gt;&lt;/a&gt;  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Back inside main.c. Printing results...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-46"&gt;&lt;/a&gt;  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Name: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Value: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_int&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-47"&gt;&lt;/a&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-48"&gt;&lt;/a&gt;  &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Freeing the RStruct data...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-49"&gt;&lt;/a&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_free&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-50"&gt;&lt;/a&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-51"&gt;&lt;/a&gt;  &lt;span class="n"&gt;dlclose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-52"&gt;&lt;/a&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;EXIT_SUCCESS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_8334087a10e5400082a4f596ff8b5e4e-53"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;This code is based on the example in the &lt;tt class="docutils literal"&gt;dlopen()&lt;/tt&gt; &lt;a class="reference external" href="https://linux.die.net/man/3/dlopen"&gt;man pages&lt;/a&gt;. In particular, the library file
is opened and a handle attached to it here:&lt;/p&gt;
&lt;pre class="code c"&gt;&lt;a name="rest_code_75b6eb5344ab4584ba11de255bdcc2c9-1"&gt;&lt;/a&gt;&lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;a name="rest_code_75b6eb5344ab4584ba11de255bdcc2c9-2"&gt;&lt;/a&gt;  &lt;span class="s"&gt;"librstruct.so"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_75b6eb5344ab4584ba11de255bdcc2c9-3"&gt;&lt;/a&gt;  &lt;span class="n"&gt;RTLD_LAZY&lt;/span&gt;
&lt;a name="rest_code_75b6eb5344ab4584ba11de255bdcc2c9-4"&gt;&lt;/a&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;A function pointer to &lt;tt class="docutils literal"&gt;data_new()&lt;/tt&gt; is created with &lt;tt class="docutils literal"&gt;dlsym()&lt;/tt&gt;, and we use the function to create
the new &lt;tt class="docutils literal"&gt;RStruct&lt;/tt&gt; instance with the lines&lt;/p&gt;
&lt;pre class="code c"&gt;&lt;a name="rest_code_9d098eaff0ac46999a9dc26da0977ae6-1"&gt;&lt;/a&gt;&lt;span class="n"&gt;data_new&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RStruct&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="n"&gt;dlsym&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"data_new"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_9d098eaff0ac46999a9dc26da0977ae6-2"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// snip&lt;/span&gt;
&lt;a name="rest_code_9d098eaff0ac46999a9dc26da0977ae6-3"&gt;&lt;/a&gt;&lt;span class="n"&gt;RStruct&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_new&lt;/span&gt;&lt;span class="p"&gt;)();&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Finally, the data is freed by creating another function pointer to &lt;tt class="docutils literal"&gt;data_free()&lt;/tt&gt; and calling it.&lt;/p&gt;
&lt;pre class="code c"&gt;&lt;a name="rest_code_cfc11c485be44561b409afeea33674f4-1"&gt;&lt;/a&gt;&lt;span class="n"&gt;data_free&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;RStruct&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="n"&gt;dlsym&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"data_free"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_cfc11c485be44561b409afeea33674f4-2"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// snip&lt;/span&gt;
&lt;a name="rest_code_cfc11c485be44561b409afeea33674f4-3"&gt;&lt;/a&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data_free&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;div class="section" id="running-the-program"&gt;
&lt;h3&gt;Running the program&lt;/h3&gt;
&lt;p&gt;I wrote a small Makefile to handle compilation of the C and Rust programs while I wrote this
post. I won't include it here because it distracts from the main message about the Rust
FFI. Instead, I will describe how to compile the program from the command line.&lt;/p&gt;
&lt;p&gt;I first placed the &lt;tt class="docutils literal"&gt;librstruct.so&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;rstruct.h&lt;/tt&gt;, and &lt;tt class="docutils literal"&gt;main.c&lt;/tt&gt; programs into the following
directory structure:&lt;/p&gt;
&lt;pre class="code console"&gt;&lt;a name="rest_code_b9fe2fa483ec4a63910b11cc01c136b4-1"&gt;&lt;/a&gt;&lt;span class="gp"&gt;$&lt;/span&gt; tree
&lt;a name="rest_code_b9fe2fa483ec4a63910b11cc01c136b4-2"&gt;&lt;/a&gt;&lt;span class="go"&gt;.&lt;/span&gt;
&lt;a name="rest_code_b9fe2fa483ec4a63910b11cc01c136b4-3"&gt;&lt;/a&gt;&lt;span class="go"&gt;├── include&lt;/span&gt;
&lt;a name="rest_code_b9fe2fa483ec4a63910b11cc01c136b4-4"&gt;&lt;/a&gt;&lt;span class="go"&gt;│   └── rstruct.h&lt;/span&gt;
&lt;a name="rest_code_b9fe2fa483ec4a63910b11cc01c136b4-5"&gt;&lt;/a&gt;&lt;span class="go"&gt;├── lib&lt;/span&gt;
&lt;a name="rest_code_b9fe2fa483ec4a63910b11cc01c136b4-6"&gt;&lt;/a&gt;&lt;span class="go"&gt;│   └── librstruct.so&lt;/span&gt;
&lt;a name="rest_code_b9fe2fa483ec4a63910b11cc01c136b4-7"&gt;&lt;/a&gt;&lt;span class="go"&gt;└── src&lt;/span&gt;
&lt;a name="rest_code_b9fe2fa483ec4a63910b11cc01c136b4-8"&gt;&lt;/a&gt;&lt;span class="go"&gt;    └── main.c&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Next, I compiled the &lt;tt class="docutils literal"&gt;main&lt;/tt&gt; binary with gcc.&lt;/p&gt;
&lt;pre class="code console"&gt;&lt;a name="rest_code_352cf378f2f64574baa4bb2b8fe8a162-1"&gt;&lt;/a&gt;&lt;span class="gp"&gt;$&lt;/span&gt; gcc -Wall -g -Iinclude -c -o main.o main.c
&lt;a name="rest_code_352cf378f2f64574baa4bb2b8fe8a162-2"&gt;&lt;/a&gt;&lt;span class="gp"&gt;$&lt;/span&gt; gcc -Wall -g -o main main.o -ldl
&lt;/pre&gt;&lt;p&gt;(&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-ldl&lt;/span&gt;&lt;/tt&gt; is used to link against libdl for dynamically loading the library from C.) After
compilation I run the &lt;tt class="docutils literal"&gt;main&lt;/tt&gt; binary. To make it work, I set the &lt;tt class="docutils literal"&gt;LD_LIBRARY_PATH&lt;/tt&gt; environment
variable so that the program knows to look inside the &lt;tt class="docutils literal"&gt;lib&lt;/tt&gt; directory for the &lt;tt class="docutils literal"&gt;librstruct.so&lt;/tt&gt;
library.&lt;/p&gt;
&lt;pre class="code console"&gt;&lt;a name="rest_code_be0943b0540b421ea0a59802a0f60cb7-1"&gt;&lt;/a&gt;&lt;span class="gp"&gt;$&lt;/span&gt; &lt;span class="nv"&gt;LD_LIBRARY_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lib ./main
&lt;a name="rest_code_be0943b0540b421ea0a59802a0f60cb7-2"&gt;&lt;/a&gt;&lt;span class="go"&gt;Loading librstruct.so...&lt;/span&gt;
&lt;a name="rest_code_be0943b0540b421ea0a59802a0f60cb7-3"&gt;&lt;/a&gt;&lt;span class="go"&gt;Done.&lt;/span&gt;
&lt;a name="rest_code_be0943b0540b421ea0a59802a0f60cb7-4"&gt;&lt;/a&gt;
&lt;a name="rest_code_be0943b0540b421ea0a59802a0f60cb7-5"&gt;&lt;/a&gt;&lt;span class="go"&gt;Calling data_new() from main.c...&lt;/span&gt;
&lt;a name="rest_code_be0943b0540b421ea0a59802a0f60cb7-6"&gt;&lt;/a&gt;&lt;span class="go"&gt;Inside data_new().&lt;/span&gt;
&lt;a name="rest_code_be0943b0540b421ea0a59802a0f60cb7-7"&gt;&lt;/a&gt;
&lt;a name="rest_code_be0943b0540b421ea0a59802a0f60cb7-8"&gt;&lt;/a&gt;&lt;span class="go"&gt;Back inside main.c. Printing results...&lt;/span&gt;
&lt;a name="rest_code_be0943b0540b421ea0a59802a0f60cb7-9"&gt;&lt;/a&gt;&lt;span class="go"&gt;Name: my_rstruct&lt;/span&gt;
&lt;a name="rest_code_be0943b0540b421ea0a59802a0f60cb7-10"&gt;&lt;/a&gt;&lt;span class="go"&gt;Value: 42&lt;/span&gt;
&lt;a name="rest_code_be0943b0540b421ea0a59802a0f60cb7-11"&gt;&lt;/a&gt;
&lt;a name="rest_code_be0943b0540b421ea0a59802a0f60cb7-12"&gt;&lt;/a&gt;&lt;span class="go"&gt;Freeing the RStruct data...&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Nice! From the output you can see the print statements that I placed inside both the Rust and C
code to indicate where the program was as it was running. In summary, the program performs the
following sequence of events:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The main binary is run&lt;/li&gt;
&lt;li&gt;The &lt;tt class="docutils literal"&gt;librstruct.so&lt;/tt&gt; library is opened and pointers to the &lt;tt class="docutils literal"&gt;data_new()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;data_free()&lt;/tt&gt;
functions are created&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;data_new()&lt;/tt&gt; is called, creating our Rust datatype on the heap and returning a pointer to it in
the C code&lt;/li&gt;
&lt;li&gt;Information about the data type is printed from C&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;data_free()&lt;/tt&gt; is called, freeing the memory from back inside Rust&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="summary"&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;And that's it! I hope you enjoyed this post. It took me several days of reading and trial-and-error
to learn about this feature of Rust. The topics covered here were&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;the Rust FFI and its purpose&lt;/li&gt;
&lt;li&gt;creating a complex data type (a Rust enum nested inside a Rust struct) and exporting it through
the FFI&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;Box&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;CString&lt;/tt&gt; Rust data types&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;cbindgen&lt;/tt&gt; for automatically creating header files from Rust code&lt;/li&gt;
&lt;li&gt;using the Rust library from inside C&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/div&gt;</description><category>c</category><category>rust</category><guid>http://kmdouglass.github.io/posts/complex-data-types-and-the-rust-ffi/</guid><pubDate>Thu, 04 Apr 2019 17:51:55 GMT</pubDate></item><item><title>A simple UNIX socket listener in Rust</title><link>http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/</link><dc:creator>Kyle M. Douglass</dc:creator><description>&lt;div&gt;&lt;p&gt;I decided that I wanted to learn a new programming language in 2019. After a bit of research, I
settled upon &lt;a class="reference external" href="https://www.rust-lang.org/"&gt;Rust&lt;/a&gt; due to its speed, novel ideas about memory safety, and &lt;a class="reference external" href="https://blog.rust-lang.org/2018/03/12/roadmap.html#four-target-domains"&gt;focus on two areas
that I am interested in&lt;/a&gt;: embedded systems and WebAssembly. While I think that &lt;a class="reference external" href="https://doc.rust-lang.org/book/"&gt;The Book&lt;/a&gt; is the
best place to get started learning the language, nothing is really a substitute for writing code.&lt;/p&gt;
&lt;p&gt;With that in mind, I developed an idea for a starting project: a background daemon for Linux
systems like the Raspberry Pi that controls and reads data from the system's peripherals. The
design of this project is inspired by Docker: a daemon process does most of the heavy work while a
command line tool communicates with the Daemon over a Unix socket (typically a file located at
&lt;tt class="docutils literal"&gt;/var/run/docker.sock&lt;/tt&gt;). The purpose of this post is to demonstrate the most basic realization of
this: reading text from a UNIX socket in Rust. And to emphasize that the UNIX socket is used for
communication between two separate processes, we will send messages from Bash to Rust.&lt;/p&gt;
&lt;p&gt;Keep in mind that this is my first-ever Rust program, so it may not be completely idiomatic
Rust. The following was compiled with rustc 1.32.0 (9fda7c223 2019-01-16).&lt;/p&gt;
&lt;p&gt;To begin, I created a new Rust project with &lt;tt class="docutils literal"&gt;cargo&lt;/tt&gt;.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_1ac0529c40624732939d365f9657b3e6-1"&gt;&lt;/a&gt;$ cargo new rust-uds
&lt;a name="rest_code_1ac0529c40624732939d365f9657b3e6-2"&gt;&lt;/a&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; rust-uds
&lt;/pre&gt;&lt;p&gt;Next, I opened the file that cargo automatically generated in &lt;tt class="docutils literal"&gt;src/main.rs&lt;/tt&gt;, removed the
auto-generated content, and added the following code, which is largely based on the &lt;a class="reference external" href="https://doc.rust-lang.org/std/os/unix/net/struct.UnixListener.html#examples"&gt;example&lt;/a&gt;
provided in the Rust documentation but with a few key differences:&lt;/p&gt;
&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-1"&gt; 1&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-2"&gt; 2&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-3"&gt; 3&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-4"&gt; 4&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-5"&gt; 5&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-6"&gt; 6&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-7"&gt; 7&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-8"&gt; 8&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-9"&gt; 9&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-10"&gt;10&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-11"&gt;11&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-12"&gt;12&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-13"&gt;13&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-14"&gt;14&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-15"&gt;15&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-16"&gt;16&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-17"&gt;17&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-18"&gt;18&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-19"&gt;19&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-20"&gt;20&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-21"&gt;21&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-22"&gt;22&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-23"&gt;23&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-24"&gt;24&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-25"&gt;25&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/#rest_code_63f11189760146ffaafa8a373168ef4c-26"&gt;26&lt;/a&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="code rust"&gt;&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;::&lt;span class="n"&gt;io&lt;/span&gt;::&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;BufRead&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BufReader&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;::&lt;span class="n"&gt;os&lt;/span&gt;::&lt;span class="n"&gt;unix&lt;/span&gt;::&lt;span class="n"&gt;net&lt;/span&gt;::&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;UnixStream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;UnixListener&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-3"&gt;&lt;/a&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;::&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-4"&gt;&lt;/a&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-5"&gt;&lt;/a&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;handle_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;: &lt;span class="nc"&gt;UnixStream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-6"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BufReader&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-7"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-8"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-9"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-10"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-11"&gt;&lt;/a&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-12"&gt;&lt;/a&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-13"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UnixListener&lt;/span&gt;::&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/tmp/rust-uds.sock"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-14"&gt;&lt;/a&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-15"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;incoming&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-16"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-17"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-18"&gt;&lt;/a&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;::&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;handle_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-19"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-20"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-21"&gt;&lt;/a&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-22"&gt;&lt;/a&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-23"&gt;&lt;/a&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-24"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-25"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_63f11189760146ffaafa8a373168ef4c-26"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;div class="section" id="explanation"&gt;
&lt;h2&gt;Explanation&lt;/h2&gt;
&lt;p&gt;The first three lines import the necessary modules for this code example.&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_89c92eb67a9b4302b8ddc395afc1b644-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;::&lt;span class="n"&gt;io&lt;/span&gt;::&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;BufRead&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BufReader&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_89c92eb67a9b4302b8ddc395afc1b644-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;::&lt;span class="n"&gt;os&lt;/span&gt;::&lt;span class="n"&gt;unix&lt;/span&gt;::&lt;span class="n"&gt;net&lt;/span&gt;::&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;UnixStream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;UnixListener&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_89c92eb67a9b4302b8ddc395afc1b644-3"&gt;&lt;/a&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;::&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;&lt;tt class="docutils literal"&gt;BufRead&lt;/tt&gt; is a trait that enables extra ways of reading data sources; in this case, it has an
internal buffer for reading the socket line-by-line. &lt;tt class="docutils literal"&gt;BufReader&lt;/tt&gt; is a struct that actually
implements the functionality in &lt;tt class="docutils literal"&gt;BufRead&lt;/tt&gt;. &lt;tt class="docutils literal"&gt;UnixStream&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;UnixListener&lt;/tt&gt; are structs that
provide the functionality for handling the UNIX socket, and the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;std::thread&lt;/span&gt;&lt;/tt&gt; module is used to
spawn threads.&lt;/p&gt;
&lt;p&gt;The next set of lines defines a function named &lt;tt class="docutils literal"&gt;handle_client()&lt;/tt&gt; that is called whenever new data
arrives in the stream. The explanation for this is best left until after the &lt;tt class="docutils literal"&gt;main()&lt;/tt&gt; function.&lt;/p&gt;
&lt;p&gt;The first line in the &lt;tt class="docutils literal"&gt;main()&lt;/tt&gt; function creates the UnixListener struct and binds it to the
&lt;tt class="docutils literal"&gt;listener&lt;/tt&gt; variable.&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_08622b1f94a34b97b092a438874b4a75-1"&gt;&lt;/a&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UnixListener&lt;/span&gt;::&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/tmp/rust-uds.sock"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The &lt;tt class="docutils literal"&gt;bind()&lt;/tt&gt; function takes a string argument that is a path to the socket file and &lt;tt class="docutils literal"&gt;unwrap()&lt;/tt&gt;
moves the value out of the Result that is returned by &lt;tt class="docutils literal"&gt;bind()&lt;/tt&gt;. (This is a pattern that is
&lt;a class="reference external" href="https://doc.rust-lang.org/std/option/enum.Option.html#method.unwrap"&gt;discouraged&lt;/a&gt; in Rust but is OK for quick prototypes because it simplifies the error handling.)&lt;/p&gt;
&lt;p&gt;After creating the listener, &lt;tt class="docutils literal"&gt;listener.incoming()&lt;/tt&gt; returns an iterator over the incoming
connections to the socket. The connections are looped over in an infinite for loop; I believe that
this is more-or-less the same as a generator in Python which never raises a &lt;tt class="docutils literal"&gt;StopIteration&lt;/tt&gt;
exception.&lt;/p&gt;
&lt;p&gt;Next, the &lt;tt class="docutils literal"&gt;Result&lt;/tt&gt; of the incoming streams is matched; if there is an error, it is printed and
the loop it exited:&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_6b902f1cd3d0440b9c7ff54253aa714a-1"&gt;&lt;/a&gt;&lt;span class="nb"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_6b902f1cd3d0440b9c7ff54253aa714a-2"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_6b902f1cd3d0440b9c7ff54253aa714a-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_6b902f1cd3d0440b9c7ff54253aa714a-4"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;However, if the &lt;tt class="docutils literal"&gt;Result&lt;/tt&gt; of the connection is &lt;tt class="docutils literal"&gt;Ok&lt;/tt&gt;, then a new thread is spawned to handle the
new stream:&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_4452be9a3e7945d6aa40ca833a2c8015-1"&gt;&lt;/a&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_4452be9a3e7945d6aa40ca833a2c8015-2"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;::&lt;span class="n"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;handle_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_4452be9a3e7945d6aa40ca833a2c8015-3"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Finally, the client handler is called for each connection.&lt;/p&gt;
&lt;pre class="code rust"&gt;&lt;a name="rest_code_5635c4196bd54613bf4f6a243c0f0023-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;handle_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;: &lt;span class="nc"&gt;UnixStream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_5635c4196bd54613bf4f6a243c0f0023-2"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BufReader&lt;/span&gt;::&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_5635c4196bd54613bf4f6a243c0f0023-3"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_5635c4196bd54613bf4f6a243c0f0023-4"&gt;&lt;/a&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unwrap&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_5635c4196bd54613bf4f6a243c0f0023-5"&gt;&lt;/a&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;a name="rest_code_5635c4196bd54613bf4f6a243c0f0023-6"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The handler in this case is fairly straight-forward. It shadows the original &lt;tt class="docutils literal"&gt;stream&lt;/tt&gt; variable by
binding it to a version of itself that has been converted to a &lt;tt class="docutils literal"&gt;BufReader&lt;/tt&gt;. Finally, it loops
over the &lt;tt class="docutils literal"&gt;lines()&lt;/tt&gt; iterator, which blocks until a new line appears in the stream.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="sending-messages"&gt;
&lt;h2&gt;Sending messages&lt;/h2&gt;
&lt;p&gt;As an example, let's send messages to the Rust program via Bash using &lt;a class="reference external" href="http://man.openbsd.org/nc"&gt;the OpenBSD version of
netcat&lt;/a&gt;. (The OpenBSD version seems to be the default on Ubuntu-based systems.) This should
underscore the fact that the UNIX socket is really being used to communicate between two different
processes.&lt;/p&gt;
&lt;p&gt;First, compile and run the Rust program to start the socket listener:&lt;/p&gt;
&lt;pre class="code text"&gt;&lt;a name="rest_code_1f620754abbe490aa93573b1e8975f6f-1"&gt;&lt;/a&gt;$ cargo run --release
&lt;a name="rest_code_1f620754abbe490aa93573b1e8975f6f-2"&gt;&lt;/a&gt;   Compiling rust-uds v0.1.0 (/home/kmd/src/rust-uds)
&lt;a name="rest_code_1f620754abbe490aa93573b1e8975f6f-3"&gt;&lt;/a&gt;    Finished release [optimized] target(s) in 1.59s
&lt;a name="rest_code_1f620754abbe490aa93573b1e8975f6f-4"&gt;&lt;/a&gt;     Running `target/release/rust-uds`
&lt;/pre&gt;&lt;p&gt;Open up a new terminal. You should see the socket file /tmp/rust-uds.sock:&lt;/p&gt;
&lt;pre class="code text"&gt;&lt;a name="rest_code_61d72e4f90db4dbc8015a44633dc3213-1"&gt;&lt;/a&gt;$ ls /tmp | grep rust
&lt;a name="rest_code_61d72e4f90db4dbc8015a44633dc3213-2"&gt;&lt;/a&gt;rust-uds.sock
&lt;/pre&gt;&lt;p&gt;Now let's send messages to the rust program. Use the following netcat command to open a connection
to the socket.&lt;/p&gt;
&lt;pre class="code text"&gt;&lt;a name="rest_code_92ea3b055e0442869c07eb9de52a4eb9-1"&gt;&lt;/a&gt;$ nc -U /tmp/rust-uds.sock
&lt;/pre&gt;&lt;p&gt;The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-U&lt;/span&gt;&lt;/tt&gt; is necessary to indicate to netcat that this is a UNIX stream socket. Now, start typing
text into the same window. Every time you press ENTER, you should see the same text appear in the
terminal window in which the Rust program is running. Press CTRL-C to exit the Rust socket
listener. If you re-run the program, delete the old socket first: &lt;tt class="docutils literal"&gt;rm &lt;span class="pre"&gt;/tmp/rust-uds.sock&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="summary"&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Use a &lt;tt class="docutils literal"&gt;UnixListener&lt;/tt&gt; struct to create a UNIX socket and listen to it for connections.&lt;/li&gt;
&lt;li&gt;For each new connection, spawn a new thread and read the stream with a &lt;tt class="docutils literal"&gt;BufReader&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Print each new line in the stream by iterating over the &lt;tt class="docutils literal"&gt;lines()&lt;/tt&gt; iterator of the
&lt;tt class="docutils literal"&gt;BufReader&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Send commands to your Rust program from bash with &lt;tt class="docutils literal"&gt;nc &lt;span class="pre"&gt;-U&lt;/span&gt; "$PATH_TO_SOCKET"&lt;/tt&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;/div&gt;</description><category>linux</category><category>rust</category><guid>http://kmdouglass.github.io/posts/a-simple-unix-socket-listener-in-rust/</guid><pubDate>Sun, 24 Feb 2019 15:25:58 GMT</pubDate></item><item><title>Linking shared libraries in Micro-Manager for Linux</title><link>http://kmdouglass.github.io/posts/linking-shared-libraries-in-micro-manager-for-linux/</link><dc:creator>Kyle M. Douglass</dc:creator><description>&lt;div&gt;&lt;p&gt;Lately I have been working on a new &lt;a class="reference external" href="https://github.com/kmdouglass/RPi-DeviceAdapters"&gt;Video4Linux2 device adapter&lt;/a&gt; for &lt;a class="reference external" href="https://micro-manager.org/"&gt;Micro-Manager&lt;/a&gt;. I
encountered the following error after adding some functionality that introduced two &lt;a class="reference external" href="https://www.boost.org/"&gt;Boost
libraries&lt;/a&gt; as new dependencies in my project.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_02df986928d44e26886a11efd12ce341-1"&gt;&lt;/a&gt;Traceback &lt;span class="o"&gt;(&lt;/span&gt;most recent call last&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;a name="rest_code_02df986928d44e26886a11efd12ce341-2"&gt;&lt;/a&gt;  File &lt;span class="s2"&gt;"RPiV4L2.py"&lt;/span&gt;, line &lt;span class="m"&gt;17&lt;/span&gt;, in &amp;lt;module&amp;gt;
&lt;a name="rest_code_02df986928d44e26886a11efd12ce341-3"&gt;&lt;/a&gt;    mmc.loadDevice&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"camera"&lt;/span&gt;, &lt;span class="s2"&gt;"RPiV4L2"&lt;/span&gt;, &lt;span class="s2"&gt;"RPiV4L2"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a name="rest_code_02df986928d44e26886a11efd12ce341-4"&gt;&lt;/a&gt;  File &lt;span class="s2"&gt;"/home/micro-manager/app/lib/micro-manager/MMCorePy.py"&lt;/span&gt;, line &lt;span class="m"&gt;3515&lt;/span&gt;, in loadDevice
&lt;a name="rest_code_02df986928d44e26886a11efd12ce341-5"&gt;&lt;/a&gt;    &lt;span class="k"&gt;return&lt;/span&gt; _MMCorePy.CMMCore_loadDevice&lt;span class="o"&gt;(&lt;/span&gt;self, label, moduleName, deviceName&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a name="rest_code_02df986928d44e26886a11efd12ce341-6"&gt;&lt;/a&gt;MMCorePy.CMMError: Failed to load device &lt;span class="s2"&gt;"RPiV4L2"&lt;/span&gt; from adapter module &lt;span class="s2"&gt;"RPiV4L2"&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; Failed to load device adapter &lt;span class="s2"&gt;"RPiV4L2"&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; Failed to load module &lt;span class="s2"&gt;"/home/micro-manager/app/lib/micro-manager/libmmgr_dal_RPiV4L2.so.0"&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; /home/micro-manager/app/lib/micro-manager/libmmgr_dal_RPiV4L2.so.0: undefined symbol: _ZN5boost10filesystem6detail13dir_itr_closeERPvS3_ &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;I received this error when I tried to load the device in a Python script. At first I was puzzled
because the code compiled without problems, but I soon found that the solution was simple.&lt;/p&gt;
&lt;p&gt;The key part of the message is &lt;tt class="docutils literal"&gt;undefined symbol:
_ZN5boost10filesystem6detail13dir_itr_closeERPvS3_&lt;/tt&gt;. To troubleshoot this, I first demangled the
symbol name by entering it at &lt;a class="reference external" href="https://demangler.com/"&gt;https://demangler.com/&lt;/a&gt;. I discovered that the symbol was referring to
the function &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;boost::filesystem::detail::dir_itr_close(void*&amp;amp;,&lt;/span&gt; &lt;span class="pre"&gt;void*&amp;amp;)&lt;/span&gt;&lt;/tt&gt;. I had added both the
Boost filesystem and Boost regex libraries to this device adapter as dependencies, so it was not
surprising that either of their names appeared in the error message.&lt;/p&gt;
&lt;p&gt;Next, I used the &lt;a class="reference external" href="http://man7.org/linux/man-pages/man1/ldd.1.html"&gt;ldd&lt;/a&gt; program to check which libraries my device adapter were linked
against. (libmmgr_dal_RPiV4l2.so.0 is the name of the device adapter library file).&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_f8dbd5a6b4be4049acdcc6c3b0b209cc-1"&gt;&lt;/a&gt;$ ldd libmmgr_dal_RPiV4L2.so.0
&lt;a name="rest_code_f8dbd5a6b4be4049acdcc6c3b0b209cc-2"&gt;&lt;/a&gt;     linux-vdso.so.1 &lt;span class="o"&gt;(&lt;/span&gt;0x7ec21000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a name="rest_code_f8dbd5a6b4be4049acdcc6c3b0b209cc-3"&gt;&lt;/a&gt;     libdl.so.2 &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; /lib/arm-linux-gnueabihf/libdl.so.2 &lt;span class="o"&gt;(&lt;/span&gt;0x76e9c000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a name="rest_code_f8dbd5a6b4be4049acdcc6c3b0b209cc-4"&gt;&lt;/a&gt;     libstdc++.so.6 &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; /usr/lib/arm-linux-gnueabihf/libstdc++.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0x76d54000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a name="rest_code_f8dbd5a6b4be4049acdcc6c3b0b209cc-5"&gt;&lt;/a&gt;     libm.so.6 &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; /lib/arm-linux-gnueabihf/libm.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0x76cdc000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a name="rest_code_f8dbd5a6b4be4049acdcc6c3b0b209cc-6"&gt;&lt;/a&gt;     libc.so.6 &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; /lib/arm-linux-gnueabihf/libc.so.6 &lt;span class="o"&gt;(&lt;/span&gt;0x76bee000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a name="rest_code_f8dbd5a6b4be4049acdcc6c3b0b209cc-7"&gt;&lt;/a&gt;     libgcc_s.so.1 &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; /lib/arm-linux-gnueabihf/libgcc_s.so.1 &lt;span class="o"&gt;(&lt;/span&gt;0x76bc1000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a name="rest_code_f8dbd5a6b4be4049acdcc6c3b0b209cc-8"&gt;&lt;/a&gt;     libicudata.so.57 &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; /usr/lib/arm-linux-gnueabihf/libicudata.so.57 &lt;span class="o"&gt;(&lt;/span&gt;0x75334000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a name="rest_code_f8dbd5a6b4be4049acdcc6c3b0b209cc-9"&gt;&lt;/a&gt;     libicui18n.so.57 &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; /usr/lib/arm-linux-gnueabihf/libicui18n.so.57 &lt;span class="o"&gt;(&lt;/span&gt;0x75187000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a name="rest_code_f8dbd5a6b4be4049acdcc6c3b0b209cc-10"&gt;&lt;/a&gt;     libicuuc.so.57 &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; /usr/lib/arm-linux-gnueabihf/libicuuc.so.57 &lt;span class="o"&gt;(&lt;/span&gt;0x7505e000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a name="rest_code_f8dbd5a6b4be4049acdcc6c3b0b209cc-11"&gt;&lt;/a&gt;     librt.so.1 &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; /lib/arm-linux-gnueabihf/librt.so.1 &lt;span class="o"&gt;(&lt;/span&gt;0x75048000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a name="rest_code_f8dbd5a6b4be4049acdcc6c3b0b209cc-12"&gt;&lt;/a&gt;     libpthread.so.0 &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; /lib/arm-linux-gnueabihf/libpthread.so.0 &lt;span class="o"&gt;(&lt;/span&gt;0x75024000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a name="rest_code_f8dbd5a6b4be4049acdcc6c3b0b209cc-13"&gt;&lt;/a&gt;     /lib/ld-linux-armhf.so.3 &lt;span class="o"&gt;(&lt;/span&gt;0x76fb4000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Neither libboost_filesystem nor libboost_regex are listed, so I knew that they were not linked with
the device adapter.&lt;/p&gt;
&lt;p&gt;There is a Makefile.am included in the directory of every device adapter in the Micro-Manager
project. This file is used by Autotools define how the device adapter should be compiled and
linked. Here is what my Makefile.am looked like:&lt;/p&gt;
&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;a href="http://kmdouglass.github.io/posts/linking-shared-libraries-in-micro-manager-for-linux/#rest_code_00c81f3febaa4837baf55d9bec9ab8e9-1"&gt;1&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/linking-shared-libraries-in-micro-manager-for-linux/#rest_code_00c81f3febaa4837baf55d9bec9ab8e9-2"&gt;2&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/linking-shared-libraries-in-micro-manager-for-linux/#rest_code_00c81f3febaa4837baf55d9bec9ab8e9-3"&gt;3&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/linking-shared-libraries-in-micro-manager-for-linux/#rest_code_00c81f3febaa4837baf55d9bec9ab8e9-4"&gt;4&lt;/a&gt;
&lt;a href="http://kmdouglass.github.io/posts/linking-shared-libraries-in-micro-manager-for-linux/#rest_code_00c81f3febaa4837baf55d9bec9ab8e9-5"&gt;5&lt;/a&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="code Makefile"&gt;&lt;a name="rest_code_00c81f3febaa4837baf55d9bec9ab8e9-1"&gt;&lt;/a&gt;&lt;span class="nv"&gt;AM_CXXFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;MMDEVAPI_CXXFLAGS&lt;span class="k"&gt;)&lt;/span&gt;
&lt;a name="rest_code_00c81f3febaa4837baf55d9bec9ab8e9-2"&gt;&lt;/a&gt;&lt;span class="nv"&gt;deviceadapter_LTLIBRARIES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; libmmgr_dal_RPiV4L2.la
&lt;a name="rest_code_00c81f3febaa4837baf55d9bec9ab8e9-3"&gt;&lt;/a&gt;&lt;span class="nv"&gt;libmmgr_dal_RPiV4L2_la_SOURCES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; RPiV4L2.cpp RPiV4L2.h refactor.h ../../MMDevice/MMDevice.h ../../MMDevice/DeviceBase.h
&lt;a name="rest_code_00c81f3febaa4837baf55d9bec9ab8e9-4"&gt;&lt;/a&gt;&lt;span class="nv"&gt;libmmgr_dal_RPiV4L2_la_LIBADD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;MMDEVAPI_LIBADD&lt;span class="k"&gt;)&lt;/span&gt;
&lt;a name="rest_code_00c81f3febaa4837baf55d9bec9ab8e9-5"&gt;&lt;/a&gt;&lt;span class="nv"&gt;libmmgr_dal_RPiV4L2_la_LDFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;MMDEVAPI_LDFLAGS&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;After experimenting a bit, I discovered that I could instruct the linker to link against shared
libraries by adding them to the &lt;tt class="docutils literal"&gt;libmmgr_dal_RPiV4L2_la_LDFLAGS&lt;/tt&gt; variable with the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-l&lt;/span&gt;&lt;/tt&gt;
flag. The resulting line now looks like:&lt;/p&gt;
&lt;pre class="code Makefile"&gt;&lt;a name="rest_code_ca9552344c1245cc91c80ec3737a83d8-1"&gt;&lt;/a&gt;&lt;span class="nv"&gt;libmmgr_dal_RPiV4L2_la_LDFLAGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;MMDEVAPI_LDFLAGS&lt;span class="k"&gt;)&lt;/span&gt; -lboost_regex -lboost_filesystem
&lt;/pre&gt;&lt;p&gt;Finally, running &lt;tt class="docutils literal"&gt;ldd&lt;/tt&gt; on the rebuilt device adapter now shows these two libraries:&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_6daa273d04d74cfaae49c56c46a05fbf-1"&gt;&lt;/a&gt;$ ldd libmmgr_dal_RPiV4L2.so.0
&lt;a name="rest_code_6daa273d04d74cfaae49c56c46a05fbf-2"&gt;&lt;/a&gt;     linux-vdso.so.1 &lt;span class="o"&gt;(&lt;/span&gt;0x7ed74000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a name="rest_code_6daa273d04d74cfaae49c56c46a05fbf-3"&gt;&lt;/a&gt;     libboost_regex.so.1.62.0 &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; /usr/lib/arm-linux-gnueabihf/libboost_regex.so.1.62.0 &lt;span class="o"&gt;(&lt;/span&gt;0x76e3c000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a name="rest_code_6daa273d04d74cfaae49c56c46a05fbf-4"&gt;&lt;/a&gt;     libboost_filesystem.so.1.62.0 &lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; /usr/lib/arm-linux-gnueabihf/libboost_filesystem.so.1.62.0 &lt;span class="o"&gt;(&lt;/span&gt;0x76e1b000&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a name="rest_code_6daa273d04d74cfaae49c56c46a05fbf-5"&gt;&lt;/a&gt;     ...
&lt;/pre&gt;&lt;/div&gt;</description><category>micro-manager</category><guid>http://kmdouglass.github.io/posts/linking-shared-libraries-in-micro-manager-for-linux/</guid><pubDate>Sat, 19 Jan 2019 11:00:37 GMT</pubDate></item><item><title>Create a custom Raspbian image with pi-gen: part 2</title><link>http://kmdouglass.github.io/posts/create-a-custom-raspbian-image-with-pi-gen-part-2/</link><dc:creator>Kyle M. Douglass</dc:creator><description>&lt;div&gt;&lt;p&gt;In my &lt;a class="reference external" href="http://kmdouglass.github.io/posts/create-a-custom-raspbian-image-with-pi-gen-part-1/"&gt;previous post&lt;/a&gt;, I discussed how to setup user accounts and
locales in a custom Raspbian image using pi-gen. In this follow-up
post, I will discuss the main problems that I want to solve:
automatically configuring the wireless network and ssh on a new
Raspberry Pi without a terminal attached directly to the Pi.&lt;/p&gt;
&lt;div class="section" id="set-up-the-wireless-network"&gt;
&lt;h2&gt;Set up the wireless network&lt;/h2&gt;
&lt;div class="section" id="the-wpa-supplicant"&gt;
&lt;h3&gt;The WPA supplicant&lt;/h3&gt;
&lt;p&gt;The Pi's wireless credentials are configured in stage 2 in the file
&lt;strong&gt;stage2/02-net-tweaks/files/wpa_supplicant.conf&lt;/strong&gt;. Here's how it
looks by default:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
&lt;/pre&gt;
&lt;p&gt;According to the blogs &lt;a class="reference external" href="https://learnthinksolvecreate.wordpress.com/2017/07/25/pi-gen-setting-default-wifi-settings/"&gt;Learn Think Solve Create&lt;/a&gt; and the &lt;a class="reference external" href="https://www.raspberrypi-spy.co.uk/2017/04/manually-setting-up-pi-wifi-using-wpa_supplicant-conf/"&gt;Raspberry
Spy&lt;/a&gt;, the first thing we should do is add our country code to the top
of this file with the line &lt;cite&gt;country=CH&lt;/cite&gt;. (Use your own country code
for this.) Next, we want to enter the details for our wireless
network, which includes its name and the password. For security
reasons that I hope are obvious, we should not store the password in
this file. Instead, we create a hash of the password and put that
inside the file. The command to create the password hash is&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_89a8d4ccb392450a8c4277b923f54354-1"&gt;&lt;/a&gt;wpa_passphrase ESSID PASSWORD &amp;gt; psk
&lt;/pre&gt;&lt;p&gt;where ESSID is our wireless network's name. Note that I also used a
space before the &lt;code class="shell"&gt;wpa_passphrase&lt;/code&gt; command to prevent the
password being written to my .bash_history file. Now, we copy and
paste the contents of the file &lt;strong&gt;psk&lt;/strong&gt; into the wpa_supplicant.conf
and remove the comment that contains the actual password:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
country=CH
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
        ssid=YOUR_ESSID_HERE
        psk=YOUR_PSK_HASH_HERE
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="configure-the-wireless-network-interfaces"&gt;
&lt;h3&gt;Configure the wireless network interfaces&lt;/h3&gt;
&lt;p&gt;After having configured the supplicant, we next move on to configuring
the network interfaces used by Raspbian. The appropriate file is found
in &lt;strong&gt;stage1/02-net-tweaks/files/interfaces&lt;/strong&gt;. In my post &lt;a class="reference external" href="http://kmdouglass.github.io/posts/connecting-a-raspberry-pi-to-a-home-linux-network/"&gt;Connecting a
Raspberry Pi to a Home Linux Network&lt;/a&gt; I described how to set up the
network interfaces by editing &lt;strong&gt;/etc/network/interfaces&lt;/strong&gt;. Much of the
information presented in that post has now been superseded in Raspbian
by the DHCP daemon. For now, we will use the interfaces file to
instruct our Pi to use DHCP and will use &lt;strong&gt;/etc/dhcpcd.conf&lt;/strong&gt; at a
later time to set up a static IP address when provisioning the Pi.&lt;/p&gt;
&lt;p&gt;We first need to make a few changes to make the interfaces file aware
of the credentials in the wpa supplicant configuration file. According
to the blog &lt;a class="reference external" href="https://kerneldriver.wordpress.com/2012/10/21/configuring-wpa2-using-wpa_supplicant-on-the-raspberry-pi/"&gt;kerneldriver&lt;/a&gt;, we need modify the
/etc/networe/interfaces file as such:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
auto lo

iface lo inet loopback
iface eth0 inet dhcp

auto wlan0
iface wlan0 inet manual
     wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp
&lt;/pre&gt;
&lt;p&gt;In the first modification, I specify that I want the wirless interface
&lt;strong&gt;wlan0&lt;/strong&gt; started automatically with &lt;cite&gt;auto wlan0&lt;/cite&gt;. Next, I specify
that the wlan0 interface should use the &lt;a class="reference external" href="https://manpages.debian.org/stretch/ifupdown/interfaces.5.en.html#The_manual_Method"&gt;manual inet address family&lt;/a&gt;
with the line &lt;cite&gt;iface wlan0 inet manual&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;According to the man pages, "[the manual] method may be used to define
interfaces for which no configuration is done by default." After this
we use the &lt;cite&gt;wpa-roam&lt;/cite&gt; command to specify the location of the
wpa_supplicant.conf file that we previously modified. The wireless
ESSID and password are therefore not defined in interfaces, but rather
reference them inside wpa_supplicant.conf.&lt;/p&gt;
&lt;p&gt;In case you noticed that wpa-roam doesn't appear as an option in
documentation on the interfaces file and were wondering why, it's
because other programs like wpasupplicant may provide additional
options to the interfaces file. A similar command is &lt;cite&gt;wpa-conf&lt;/cite&gt;, but I
do not quite yet understand the difference between these two commands.&lt;/p&gt;
&lt;p&gt;Following the wpa-roam command, we configure the default options for
all networks in our wpa_supplicant.conf file with the line &lt;cite&gt;iface
default inet dhcp&lt;/cite&gt;. At this point, we save the setup of the static IP
address for a later time.&lt;/p&gt;
&lt;p&gt;For more information, see &lt;a class="reference external" href="https://manpages.debian.org/stretch/ifupdown/interfaces.5.en.html"&gt;the interfaces man page for Debian
Stretch&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="change-the-hostname"&gt;
&lt;h3&gt;Change the hostname&lt;/h3&gt;
&lt;p&gt;Our Pi's hostname may be changed from the default (raspberrypi) by
modifying the line in &lt;strong&gt;stage1/02-net-tweaks/files/hostname&lt;/strong&gt;. See
&lt;a class="reference external" href="https://tools.ietf.org/html/rfc1178"&gt;RFC 1178&lt;/a&gt; for tips on choosing a hostname.&lt;/p&gt;
&lt;p&gt;In addition to modifying the hostname file, we need to update
&lt;strong&gt;stage1/02-net-tweaks/00-patches/01-hosts.diff&lt;/strong&gt; and change
raspberrypi to the new hostname:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Index: jessie-stage1/rootfs/etc/hosts
===================================================================
--- jessie-stage1.orig/rootfs/etc/hosts
+++ jessie-stage1/rootfs/etc/hosts
@@ -3,3 +3,4 @@
 ff02::1                ip6-allnodes
 ff02::2                ip6-allrouters

+127.0.1.1      NEW_HOSTNAME_HERE
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="set-the-dns-servers"&gt;
&lt;h3&gt;Set the DNS servers&lt;/h3&gt;
&lt;p&gt;DNS servers are configured in
&lt;strong&gt;export-image/02-network/files/resolv.conf&lt;/strong&gt;. By default, mine was
already configured to use one of Google's DNS servers (8.8.8.8). I
added a secondary Google DNS address as well:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
nameserver 8.8.8.8
nameserver 8.8.4.4
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="enable-ssh"&gt;
&lt;h2&gt;Enable SSH&lt;/h2&gt;
&lt;p&gt;Enabling SSH is simple. Open &lt;strong&gt;stage2/01-sys-tweaks/01-run.sh&lt;/strong&gt; and
change the line &lt;code class="shell"&gt;systemctl disable ssh&lt;/code&gt; to &lt;code class="shell"&gt;systemctl
&lt;span class="nb"&gt;enable&lt;/span&gt; ssh&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;(I later learned that we can also enable ssh on a headless pi by
adding an empty file named &lt;strong&gt;ssh&lt;/strong&gt; to the boot partition of a standard
Raspbian image. See here for more details:
&lt;a class="reference external" href="https://www.raspberrypi.org/documentation/remote-access/ssh/"&gt;https://www.raspberrypi.org/documentation/remote-access/ssh/&lt;/a&gt;)&lt;/p&gt;
&lt;div class="section" id="configuring-ssh-keys-or-not"&gt;
&lt;h3&gt;Configuring SSH keys (or not)&lt;/h3&gt;
&lt;p&gt;I decided after writing much of this tutorial that pi-gen was not
necessarily the best tool for adding my public SSH keys. So long as I
have network access and SSH enabled, I can easily add my keys using
&lt;code class="shell"&gt;ssh-copy-id&lt;/code&gt;. Furthermore, after following this tutorial,
there still remains a lot of setup and customization steps. These can
more easily be performed manually or by server automation tools like
&lt;a class="reference external" href="http://www.fabfile.org/"&gt;Fabric&lt;/a&gt; or &lt;a class="reference external" href="https://www.ansible.com/"&gt;Ansible&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Therefore, I think that at this point we can stop with our
customization of the image with pi-gen and move to a different
tool. We have a basic Raspbian image that is already configured for
our home network and that serves as a starting point for more complete
customization.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This tutorial and my &lt;a class="reference external" href="http://kmdouglass.github.io/posts/create-a-custom-raspbian-image-with-pi-gen-part-1/"&gt;previous post&lt;/a&gt; demonstrated how to create a
custom Raspbian image that is pre-configured for&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;our home wireless network&lt;/li&gt;
&lt;li&gt;our locale information&lt;/li&gt;
&lt;li&gt;ssh&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course, we can do much, much more with pi-gen, but other tools
exist for the purpose of configuring a server. These tutorials at
least allow you to setup a new Raspberry Pi without having to manually
configure its most basic functionality. Happy Pi'ing!&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;</description><category>devops</category><category>raspberry pi</category><category>raspbian</category><guid>http://kmdouglass.github.io/posts/create-a-custom-raspbian-image-with-pi-gen-part-2/</guid><pubDate>Tue, 24 Jul 2018 16:25:26 GMT</pubDate></item><item><title>Create a custom Raspbian image with pi-gen: part 1</title><link>http://kmdouglass.github.io/posts/create-a-custom-raspbian-image-with-pi-gen-part-1/</link><dc:creator>Kyle M. Douglass</dc:creator><description>&lt;div&gt;&lt;p&gt;Docker has been an amazing tool for improving my development
efficiency on the Raspberry Pi. For example, I recently used it to
&lt;a class="reference external" href="http://kmdouglass.github.io/posts/how-i-built-a-cross-compilation-workflow-for-the-raspberry-pi/"&gt;cross-compile a large C++ and Python library&lt;/a&gt; for the Pi's ARM
architecture on my x86_64 laptop. However, in that post I took it for
granted that I had already set up my Raspberry Pi with user accounts,
packages, ssh keys, etc. Performing these steps manually on a fresh
install of the Pi's &lt;a class="reference external" href="https://www.raspberrypi.org/downloads/raspbian/"&gt;Raspbian&lt;/a&gt; operating system can become tedious,
especially because ssh needs to be manually enabled before doing any
remote work.&lt;/p&gt;
&lt;p&gt;Fortunately, the Raspberry Pi developers have provided us with
&lt;a class="reference external" href="https://github.com/RPi-Distro/pi-gen"&gt;pi-gen&lt;/a&gt;, a useful collection of Shell scripts and a Docker container
for creating custom Raspbian images. In this post, I will summarize
the steps that I take in using pi-gen to create my own, personalized
Raspbian image.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;After I wrote this post, I found a set of posts at&lt;/em&gt; &lt;a class="reference external" href="https://learnthinksolvecreate.wordpress.com/category/raspberry-pi/pi-gen/"&gt;Learn Think
Solve Create&lt;/a&gt; &lt;em&gt;that describe many of the tasks I explain here. Be
sure to check them out for another take on modifying Raspbian images.&lt;/em&gt;&lt;/p&gt;
&lt;div class="section" id="clone-the-pi-gen-repository"&gt;
&lt;h2&gt;Clone the pi-gen repository&lt;/h2&gt;
&lt;p&gt;This is as easy as cloning the git repository.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_db419c32ee174b79bcf51fa6499e641c-1"&gt;&lt;/a&gt;git clone git@github.com:RPi-Distro/pi-gen.git
&lt;/pre&gt;&lt;p&gt;Alternatively, you can use the https address instead of ssh, which is
&lt;a class="reference external" href="https://github.com/RPi-Distro/pi-gen.git"&gt;https://github.com/RPi-Distro/pi-gen.git&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;From now on, all directories in this post will be relative to the root
pi-gen directory.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="build-the-official-raspbian-images"&gt;
&lt;h2&gt;Build the official Raspbian images&lt;/h2&gt;
&lt;p&gt;By default, the pi-gen repository will build the official Raspbian
images. Doing this once before making any modifications is probably a
good idea; if you can't build the official images, how will you be
able to build a custom image?&lt;/p&gt;
&lt;p&gt;There are two main scripts that you can use to do this: &lt;strong&gt;build.sh&lt;/strong&gt;
and &lt;strong&gt;build-docker.sh&lt;/strong&gt;. build.sh requires you to install the packages
that are listed in the repository's README.md file, whereas
build-docker.sh requires only that you have Docker already installed
on your computer. I'm going to be using the Docker-based build script
for the rest of this post. If you don't have Docker installed on your
system, you can &lt;a class="reference external" href="https://docs.docker.com/install/"&gt;follow the instructions here&lt;/a&gt; for the community
edition.&lt;/p&gt;
&lt;div class="section" id="name-your-image"&gt;
&lt;h3&gt;Name your image&lt;/h3&gt;
&lt;p&gt;First we need to give a name to our image, even if we use the default
build. To do this, we assign a name to a variable called &lt;strong&gt;IMG_NAME&lt;/strong&gt;
inside a file called &lt;strong&gt;config&lt;/strong&gt; that is located inside the root pi-gen
folder.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_cac3bac8a65b4d589474934b67cbd8d0-1"&gt;&lt;/a&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"IMG_NAME=my_name"&lt;/span&gt; &amp;gt; config
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="build-the-default-image"&gt;
&lt;h3&gt;Build the default image&lt;/h3&gt;
&lt;p&gt;Once we've named our image, we can go ahead and run the build script.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_44c57045177a40a0bc8a08b56f00bd61-1"&gt;&lt;/a&gt;./build-docker.sh
&lt;/pre&gt;&lt;p&gt;Be prepared to wait a while when running this script; the full build
took well over half an hour on my laptop and with the Docker volume
located on a SSD. It also consumed several GB of space on the SSD.&lt;/p&gt;
&lt;div class="section" id="resuming-a-failed-build"&gt;
&lt;h4&gt;Resuming a failed build&lt;/h4&gt;
&lt;p&gt;The first time I used pi-gen the build failed twice. Once, it hung
without doing anything for several minutes, so I canceled it with a
&lt;strong&gt;Ctrl-C&lt;/strong&gt; command. The other time I encountered a hash error when
installing a Debian package.&lt;/p&gt;
&lt;p&gt;We can resume a failed build from the point of failure by assigning
the value 1 to the CONTINUE variable when calling build-docker.sh
again.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_fd6fe9df7b224f48b1736e341ae377dc-1"&gt;&lt;/a&gt;&lt;span class="nv"&gt;CONTINUE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; ./build-docker.sh
&lt;/pre&gt;&lt;p&gt;If we don't want to run previously built stages, we can simply place a
file inside the corresponding folder named SKIP. For example, if our
build fails at stage2, we can place SKIP files inside the stage0 and
stage1 folders, then rerun the build-docker.sh script with
CONTINUE=1.&lt;/p&gt;
&lt;p&gt;Unfortunately, I have sometimes noticed that I have to also rebuild
the stage &lt;em&gt;prior&lt;/em&gt; to the one where the build failed. In the worst
case, I had to rebuild all the stages because the fixes I applied to a
file in stage2 were not accounted for when I tried to skip building
stages 0 and 1. YMMV with this; I have no idea how well the SKIP
mechanism works for the normal build.sh script.&lt;/p&gt;
&lt;p&gt;After a successful build, we can find our custom images located inside
the &lt;strong&gt;deploy&lt;/strong&gt; folder of the pi-gen directory. These may then be
written onto a SD card and used as a standard Raspbian image.&lt;/p&gt;
&lt;p&gt;We can ensure that the build container is preserved even after successful
builds using&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_e379a9311cf54c33806ff733d2694d97-1"&gt;&lt;/a&gt;&lt;span class="nv"&gt;PRESERVE_CONTAINER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; ./build-docker.sh
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="custom-raspbian-images"&gt;
&lt;h2&gt;Custom Raspbian images&lt;/h2&gt;
&lt;p&gt;Now that we've got the default build working, let's start by
customizing the build process. For this post, I have the following
goals:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Build only the &lt;em&gt;lite&lt;/em&gt; version of the Raspbian images&lt;/li&gt;
&lt;li&gt;Add a custom user account and delete the default &lt;em&gt;pi&lt;/em&gt; account&lt;/li&gt;
&lt;li&gt;Set the Pi's locale information&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In a follow-up post, I will discuss the following:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Setup the WiFi for a home network&lt;/li&gt;
&lt;li&gt;Setup ssh so that we can log on to the Pi remotely on its first
startup&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="section" id="building-just-raspbian-lite"&gt;
&lt;h3&gt;Building just Raspbian Lite&lt;/h3&gt;
&lt;p&gt;Raspbian Lite is a &lt;a class="reference external" href="https://raspberrypi.stackexchange.com/questions/39932/differences-between-raspbian-jessie-and-raspbian-jessie-lite#39933"&gt;minimal Raspbian image&lt;/a&gt; without the X windows
server and speciality modules that would otherwise make Raspbian more
user friendly. It's an ideal starting point for projects that are
highly specialized, require only a few packages, and do not require a
GUI.&lt;/p&gt;
&lt;p&gt;pi-gen creates Raspbian images in sequential steps called stages. At
the time of this writing, there were five stages, with stages 2, 4,
and 5 producing images of the operating system. Building everything
from stage 0 up to and including stage 2 produces a Raspbian Lite
image. We can speed up the build process and save harddrive space by
disabling all the later stages.&lt;/p&gt;
&lt;p&gt;To disable the build for a particular a stage, we add an empty file
called &lt;strong&gt;SKIP&lt;/strong&gt; inside the corresponding stage folder of the pi-gen
root directory, just as we did above when skipping previously built
stages. We also disable the explicit creation of images by adding an
empty file called &lt;strong&gt;SKIP_IMAGES&lt;/strong&gt; to stages 4 and 5. (We don't need to
add a SKIP_IMAGES file to the stage3 folder because no image is
produced at this stage.)&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_990994ad730949059c3ae65fd240c93d-1"&gt;&lt;/a&gt;touch ./stage3/SKIP ./stage4/SKIP ./stage5/SKIP
&lt;a name="rest_code_990994ad730949059c3ae65fd240c93d-2"&gt;&lt;/a&gt;touch ./stage4/SKIP_IMAGES ./stage5/SKIP_IMAGES
&lt;/pre&gt;&lt;p&gt;Now, when we run build-docker.sh, pi-gen will only build and produce
one image for Raspbian Lite in the deploy directory.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="add-a-custom-user-account"&gt;
&lt;h3&gt;Add a custom user account&lt;/h3&gt;
&lt;p&gt;The default user in Raspbian is called &lt;strong&gt;pi&lt;/strong&gt;. This account is created
in stage1 in the the script &lt;strong&gt;stage1/01-sys-tweaks/00-run.sh&lt;/strong&gt;. This
account is not very secure because it and its password, &lt;em&gt;raspberry&lt;/em&gt;,
are the well-known defaults in Raspbian. Let's go ahead and change
them.&lt;/p&gt;
&lt;p&gt;The relevant lines in the script look like this:&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_f342c92a6d6c4693ad1676a0ec27cfc1-1"&gt;&lt;/a&gt;on_chroot &lt;span class="s"&gt;&amp;lt;&amp;lt; EOF&lt;/span&gt;
&lt;a name="rest_code_f342c92a6d6c4693ad1676a0ec27cfc1-2"&gt;&lt;/a&gt;&lt;span class="s"&gt;if ! id -u pi &amp;gt;/dev/null 2&amp;gt;&amp;amp;1; then&lt;/span&gt;
&lt;a name="rest_code_f342c92a6d6c4693ad1676a0ec27cfc1-3"&gt;&lt;/a&gt;&lt;span class="s"&gt;     adduser --disabled-password --gecos "" pi&lt;/span&gt;
&lt;a name="rest_code_f342c92a6d6c4693ad1676a0ec27cfc1-4"&gt;&lt;/a&gt;&lt;span class="s"&gt;fi&lt;/span&gt;
&lt;a name="rest_code_f342c92a6d6c4693ad1676a0ec27cfc1-5"&gt;&lt;/a&gt;&lt;span class="s"&gt;echo "pi:raspberry" | chpasswd&lt;/span&gt;
&lt;a name="rest_code_f342c92a6d6c4693ad1676a0ec27cfc1-6"&gt;&lt;/a&gt;&lt;span class="s"&gt;echo "root:root" | chpasswd&lt;/span&gt;
&lt;a name="rest_code_f342c92a6d6c4693ad1676a0ec27cfc1-7"&gt;&lt;/a&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The user pi is created with the line
&lt;code class="shell"&gt;adduser --disabled-password --gecos &lt;span class="s2"&gt;""&lt;/span&gt; pi&lt;/code&gt; if it doesn't
already exist. According to the &lt;a class="reference external" href="http://manpages.ubuntu.com/manpages/trusty/man8/adduser.8.html"&gt;adduser man pages&lt;/a&gt;
The --disabled-password flag prevents the program passwd from setting
the account's password when adduser is run, but remote logins without
password authentication to the pi account are still allowed. the
&lt;code class="shell"&gt;--gecos &lt;span class="s2"&gt;""&lt;/span&gt;&lt;/code&gt; flag simply adds an empty string to the
/etc/passwd file for the pi account.&lt;/p&gt;
&lt;p&gt;After the user is created, &lt;em&gt;raspberry&lt;/em&gt; is set as pi's password and
&lt;em&gt;root&lt;/em&gt; is set as the root password in the lines &lt;code class="shell"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;
&lt;span class="s2"&gt;"pi:raspberry"&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; chpasswd&lt;/code&gt; and &lt;code class="shell"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"root:root"&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; chpasswd&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let's start by modifying the pi account. For the sake of this example,
let's change its name to alphapi. For the password, we will generate a
&lt;strong&gt;temporary, random&lt;/strong&gt; password and write it to a file in the deploy
directory. We'll do the same for root. The modifications look like the
following:&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_fbc787ef08fb44148b681cb15056f252-1"&gt;&lt;/a&gt;&lt;span class="nv"&gt;user_passwd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&amp;lt; /dev/urandom tr -dc _A-Z-a-z-0-9 &lt;span class="p"&gt;|&lt;/span&gt; head -c&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;8&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;a name="rest_code_fbc787ef08fb44148b681cb15056f252-2"&gt;&lt;/a&gt;&lt;span class="nv"&gt;root_passwd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&amp;lt; /dev/urandom tr -dc _A-Z-a-z-0-9 &lt;span class="p"&gt;|&lt;/span&gt; head -c&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;8&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;a name="rest_code_fbc787ef08fb44148b681cb15056f252-3"&gt;&lt;/a&gt;
&lt;a name="rest_code_fbc787ef08fb44148b681cb15056f252-4"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Write passwords to a file.&lt;/span&gt;
&lt;a name="rest_code_fbc787ef08fb44148b681cb15056f252-5"&gt;&lt;/a&gt;cat &lt;span class="s"&gt;&amp;lt;&amp;lt;EOF &amp;gt; /pi-gen/deploy/users&lt;/span&gt;
&lt;a name="rest_code_fbc787ef08fb44148b681cb15056f252-6"&gt;&lt;/a&gt;&lt;span class="s"&gt;${user_passwd}&lt;/span&gt;
&lt;a name="rest_code_fbc787ef08fb44148b681cb15056f252-7"&gt;&lt;/a&gt;&lt;span class="s"&gt;${root_passwd}&lt;/span&gt;
&lt;a name="rest_code_fbc787ef08fb44148b681cb15056f252-8"&gt;&lt;/a&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;a name="rest_code_fbc787ef08fb44148b681cb15056f252-9"&gt;&lt;/a&gt;
&lt;a name="rest_code_fbc787ef08fb44148b681cb15056f252-10"&gt;&lt;/a&gt;on_chroot &lt;span class="s"&gt;&amp;lt;&amp;lt; EOF&lt;/span&gt;
&lt;a name="rest_code_fbc787ef08fb44148b681cb15056f252-11"&gt;&lt;/a&gt;&lt;span class="s"&gt;if ! id -u alphapi &amp;gt;/dev/null 2&amp;gt;&amp;amp;1; then&lt;/span&gt;
&lt;a name="rest_code_fbc787ef08fb44148b681cb15056f252-12"&gt;&lt;/a&gt;&lt;span class="s"&gt;     adduser --disabled-password --gecos "" alphapi&lt;/span&gt;
&lt;a name="rest_code_fbc787ef08fb44148b681cb15056f252-13"&gt;&lt;/a&gt;&lt;span class="s"&gt;fi&lt;/span&gt;
&lt;a name="rest_code_fbc787ef08fb44148b681cb15056f252-14"&gt;&lt;/a&gt;&lt;span class="s"&gt;echo "alphapi:${user_passwd}" | chpasswd&lt;/span&gt;
&lt;a name="rest_code_fbc787ef08fb44148b681cb15056f252-15"&gt;&lt;/a&gt;&lt;span class="s"&gt;echo "root:${root_passwd}" | chpasswd&lt;/span&gt;
&lt;a name="rest_code_fbc787ef08fb44148b681cb15056f252-16"&gt;&lt;/a&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The first two lines create random alphanumeric passwords for the users
alphapi and root. They should be changed immediately when the image is
first run.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_4e749f4c258b4dc5afda8e0a906eb803-1"&gt;&lt;/a&gt;&lt;span class="nv"&gt;user_passwd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&amp;lt; /dev/urandom tr -dc _A-Z-a-z-0-9 &lt;span class="p"&gt;|&lt;/span&gt; head -c&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;8&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;a name="rest_code_4e749f4c258b4dc5afda8e0a906eb803-2"&gt;&lt;/a&gt;&lt;span class="nv"&gt;root_passwd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&amp;lt; /dev/urandom tr -dc _A-Z-a-z-0-9 &lt;span class="p"&gt;|&lt;/span&gt; head -c&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;8&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;This way of password generation works by reading random bytes from
/dev/urandom and redirecting them to the standard input of the tr
command, which filters the input so only alphanumeric characters
remain. Next, the output is piped to the head command, which outputs
only the first eight alphanumeric characters produced in this fashion.&lt;/p&gt;
&lt;p&gt;The passwords are then written to a file named &lt;strong&gt;users&lt;/strong&gt; inside the
deploy directory where the outputs will eventually be placed.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_bba80531265646e4bda4259e7755a514-1"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Write passwords to a file.&lt;/span&gt;
&lt;a name="rest_code_bba80531265646e4bda4259e7755a514-2"&gt;&lt;/a&gt;cat &lt;span class="s"&gt;&amp;lt;&amp;lt;EOF &amp;gt; /pi-gen/deploy/users&lt;/span&gt;
&lt;a name="rest_code_bba80531265646e4bda4259e7755a514-3"&gt;&lt;/a&gt;&lt;span class="s"&gt;${user_passwd}&lt;/span&gt;
&lt;a name="rest_code_bba80531265646e4bda4259e7755a514-4"&gt;&lt;/a&gt;&lt;span class="s"&gt;${root_passwd}&lt;/span&gt;
&lt;a name="rest_code_bba80531265646e4bda4259e7755a514-5"&gt;&lt;/a&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The remaining parts of the script are more-or-less the same as before,
except I changed pi to alphapi and used variable substitution for the
passwords.&lt;/p&gt;
&lt;p&gt;Running ./build-docker.sh at this point will raise an error in stage02
because it's at this stage where the user pi is added to the various
groups on the system. We therefore need to open
&lt;strong&gt;stage2/01-sys-tweaks/01-run.sh&lt;/strong&gt; and modify the following lines,
replacing pi with alphapi.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_7d3b5f0a9ce949949be9de68b5a6e323-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;for&lt;/span&gt; GRP in adm dialout cdrom audio users sudo video games plugdev input gpio spi i2c netdev&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;a name="rest_code_7d3b5f0a9ce949949be9de68b5a6e323-2"&gt;&lt;/a&gt;    adduser alphapi &lt;span class="nv"&gt;$GRP&lt;/span&gt;
&lt;a name="rest_code_7d3b5f0a9ce949949be9de68b5a6e323-3"&gt;&lt;/a&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="set-the-locale-information"&gt;
&lt;h3&gt;Set the locale information&lt;/h3&gt;
&lt;p&gt;The locale information used by your operating system may be modified
as follows. Open &lt;strong&gt;stage0/01-locale/00-debconf&lt;/strong&gt;. I personally changed
every occurence of en_GB.UTF-8 to en_US.UTF-8, but you can set your
locale accordingly.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_be5df10afbc9427ca4da70e476c69892-1"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Locales to be generated:&lt;/span&gt;
&lt;a name="rest_code_be5df10afbc9427ca4da70e476c69892-2"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Choices: All locales, aa_DJ ISO-8859-1, aa_DJ.UTF-8 UTF-8, ...&lt;/span&gt;
&lt;a name="rest_code_be5df10afbc9427ca4da70e476c69892-3"&gt;&lt;/a&gt;locales locales/locales_to_be_generated multiselect en_US.UTF-8 UTF-8
&lt;a name="rest_code_be5df10afbc9427ca4da70e476c69892-4"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Default locale for the system environment:&lt;/span&gt;
&lt;a name="rest_code_be5df10afbc9427ca4da70e476c69892-5"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Choices: None, C.UTF-8, en_US.UTF-8&lt;/span&gt;
&lt;a name="rest_code_be5df10afbc9427ca4da70e476c69892-6"&gt;&lt;/a&gt;locales locales/default_environment_locale   &lt;span class="k"&gt;select&lt;/span&gt;  en_US.UTF-8
&lt;/pre&gt;&lt;p&gt;Next, we open &lt;strong&gt;stage2/01-sys-tweaks/00-debconf&lt;/strong&gt;. I currently live in
Europe, so I made the following changes:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
tzdata        tzdata/Areas    select  Europe
&lt;/pre&gt;
&lt;p&gt;I also made the following changes to switch from the default British
English to American English:&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_c015bf5c41cb4d11808ed86bad8bfee5-1"&gt;&lt;/a&gt;keyboard-configuration keyboard-configuration/xkb-keymap &lt;span class="k"&gt;select&lt;/span&gt; us
&lt;a name="rest_code_c015bf5c41cb4d11808ed86bad8bfee5-2"&gt;&lt;/a&gt;keyboard-configuration keyboard-configuration/fvariant  &lt;span class="k"&gt;select&lt;/span&gt;  English &lt;span class="o"&gt;(&lt;/span&gt;US&lt;span class="o"&gt;)&lt;/span&gt; - English &lt;span class="o"&gt;(&lt;/span&gt;US&lt;span class="se"&gt;\,&lt;/span&gt; international with dead keys&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Note that the comment in 00-debconf above the
keyboard-configuration/xkb-keymap line erroneously states that
American English is an option, but it's not. You need to change it
from "gb" to "us" if you want the American layout.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="using-the-custom-image"&gt;
&lt;h2&gt;Using the custom image&lt;/h2&gt;
&lt;p&gt;With all these changes, we can build our new image by running
&lt;code class="shell"&gt;./build-docker.sh&lt;/code&gt; and, if successful, find a .zip file inside
the deploy directory with the image name and date.&lt;/p&gt;
&lt;p&gt;To use this image, we unzip the file to extract the .img file inside
it. Next, we need to copy it onto a SD card that will plug into the
pi. I have a SD card reader/writer on my laptop for which I check for
its Linux device name by running &lt;code class="shell"&gt;lsblk&lt;/code&gt; before and after
plugging in the card. (The device that appears in the output of lsblk
after plugging it in is its name, which is &lt;strong&gt;/dev/mmcblk0&lt;/strong&gt; on my
laptop). Once I get its device name, I use the Linux &lt;code class="shell"&gt;dd&lt;/code&gt;
command to copy the contents of the image onto the card. (Be sure to
change /dev/mccblk0 to match the name that your system gives to your
SD card device.)&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_f7693cac2fa34488bc491db627f3c064-1"&gt;&lt;/a&gt;sudo dd &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2018&lt;/span&gt;-07-21-my_name-lite.img &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/mmcblk0 &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; sync
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Please be EXTREMELY careful that you get the device name right.&lt;/strong&gt;
It's not very difficult to write the contents of the image file over
your root partition or other important data.&lt;/p&gt;
&lt;p&gt;After writing the image, we can plug the SD card into our pi, boot it
up, and try logging in as alphapi with the random password that was
created in the users file. &lt;strong&gt;Be sure at this point to change your
user's and root's password&lt;/strong&gt;. We can also verify that the keyboard was
set to US English by typing Shift-3 and observing whether we get a
hashtag (#) symbol and not the symbol for the British pound currency.&lt;/p&gt;
&lt;p&gt;In a follow-up post, I will describe how to setup the network and SSH
so I can continue to setup my Raspberry Pi without ever needing a
terminal.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;</description><category>devops</category><category>raspberry pi</category><category>raspbian</category><guid>http://kmdouglass.github.io/posts/create-a-custom-raspbian-image-with-pi-gen-part-1/</guid><pubDate>Sat, 21 Jul 2018 10:31:28 GMT</pubDate></item><item><title>How I built a cross-compilation workflow for the Raspberry Pi</title><link>http://kmdouglass.github.io/posts/how-i-built-a-cross-compilation-workflow-for-the-raspberry-pi/</link><dc:creator>Kyle M. Douglass</dc:creator><description>&lt;div&gt;&lt;p&gt;Some of you may know I tinker with the Raspberry Pi in my free time
and that one of my current projects is to build a lensless microscope
with the Pi as the brains. To control the microscope, I decided a
while ago that I would use &lt;a class="reference external" href="https://micro-manager.org/wiki/Micro-Manager"&gt;Micro-Manager&lt;/a&gt;, an open-source
software package for microscope control. I made this decision for a
few reasons:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;I already knew the Micro-Manager codebase since I use it frequently
at work.&lt;/li&gt;
&lt;li&gt;The Micro-Manager core provides a device-independent interface to
hardware.&lt;/li&gt;
&lt;li&gt;I've contributed to the project in the past and feel a sense of
loyalty to the project and the people involved. Expanding
Micro-Manager into embedded microscopy would be a great way for me
to give back to the community.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Building Micro-Manager from source code presents its own set of
challenges. After ensuring that you have the correct build
environment, you need to actually compile it, and here's where things
get tricky in Raspyberry Pi development. The Pi has an ARM processor,
whereas most laptops and workstations use a x86_64 processor. This
means that code compiled on a typical desktop PC will not work on the
Pi. As I showed in &lt;a class="reference external" href="https://kmdouglass.github.io/posts/micro-manager-on-the-raspberry-pi.html"&gt;my earlier post&lt;/a&gt;,
you can compile the code directly on the Pi to circumvent this, but
this unfortunately is quite cumbersome because the code base and
dependencies are quite large. (They are nearly 8 GB in
total). Furthermore, compiling the project on the Pi is slow and
requires connecting to it via ssh or working directly on a TV screen
or monitor.&lt;/p&gt;
&lt;p&gt;These problems extend beyond Micro-Manager to other large-scale
projects that require code compilation for a specific processor
architecture. In this post, I'll describe the workflow that I
developed for cross-compiling projects for the Raspberry Pi.&lt;/p&gt;
&lt;div class="section" id="previous-attempts"&gt;
&lt;h2&gt;Previous attempts&lt;/h2&gt;
&lt;p&gt;Prior to the workflow that is the main topic of this post, I managed
to cross-compile Micro-Manager using a &lt;cite&gt;chroot&lt;/cite&gt; environment and the
&lt;a class="reference external" href="https://www.qemu.org/"&gt;QEMU emulator&lt;/a&gt;. &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Chroot"&gt;chroot&lt;/a&gt; is a Linux command that
changes the apparent root (or '/') directory for a running
process. With this approach, I mount an image of the &lt;a class="reference external" href="https://www.raspberrypi.org/downloads/raspbian/"&gt;Raspbian
operating system&lt;/a&gt;
that contains the gcc and g++ compilers and libraries for the ARM
architecture. Then, I chroot into the image and run a setup script
that builds the software. During execution of this script, the QEMU
static libraries run the ARM compilers from within the chroot
environment to build the project. The compiled code remains inside the
image, which I then burn onto a micro SD card to insert into the Pi. I
uploaded &lt;a class="reference external" href="https://gist.github.com/kmdouglass/38e1383c7e62745f3cf522702c21cb49"&gt;a gist of the bash script&lt;/a&gt;
which orchestrates all this, and my inspiration for this approach came
from a great series of blog posts from &lt;a class="reference external" href="https://disconnected.systems/blog/custom-rpi-image-with-github-travis/"&gt;Disconnected Systems&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ultimately this approach is a huge amount of work. As you can see in
the gist, it's fairly complicated bash scripting that's not easy to
debug. Furthermore, the setup script that is run inside the image
needs to do a lot of work beyond cross-compiling, like setting up the
user, permissions, network, etc. Debugging the final product is also a
challenge because you need to verify that it's working on the Pi,
which requires burning the image to a micro SD card.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="cross-compiling-with-docker"&gt;
&lt;h2&gt;Cross-compiling with Docker&lt;/h2&gt;
&lt;p&gt;After a bit of research I decided I would try instead to use &lt;a class="reference external" href="https://www.docker.com/"&gt;Docker&lt;/a&gt; for cross-compilation and deployment to
the Pi. I had just started using Docker at work to build reproducible
environments for scientific computing research. In particular, and
unlike my chroot script, I had learned that a Docker container that
built the project could work on nearly any system that had Docker
installed. Furthermore, deploying updates can be done on any Raspberry
Pi that's running Docker.&lt;/p&gt;
&lt;p&gt;I liked the idea of a portable cross-compilation workflow, so I dove
into the Docker documentation and managed to get everything working in
a few weeks of tinkering at home.&lt;/p&gt;
&lt;div class="section" id="an-overview-of-docker"&gt;
&lt;h3&gt;An overview of Docker&lt;/h3&gt;
&lt;p&gt;You can find many resources online about Docker, so I won't go into
the details here. The main thing you need to know is that Docker is a
system for creating, running, and sharing &lt;em&gt;containers&lt;/em&gt;, which are
something like light weight virtual machines. Containers solve the
problem in software development of how to build and deploy programs
that have a complex set of dependencies. It does this by isolating the
environment in which a program runs from the rest of the operating
system. For example, if you have a computer that has a certain version
of gcc (the GNU C compiler) installed, but your application requires a
different version, then you can install the required gcc along with
your application inside a container and they will not interfere with
the version of gcc that belongs to your operating system. This also
means that you can send your container to any machine that has Docker
installed and it should just run without having to do any setup.&lt;/p&gt;
&lt;p&gt;Other important things to know about Docker are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;There are two main types of objects: images and containers. Images
are sort of like blueprints that define what is inside a container,
whereas containers are like the actual buildings specified by the
blueprints. There can be many containers that come from a single
image.&lt;/li&gt;
&lt;li&gt;Containers are meant to be immutable. When you stop them and restart
them, they always restart in the same state as when they were first
created.&lt;/li&gt;
&lt;li&gt;Since containers are immutable, some of your application data may
need to be placed in a volume, which is either another container or
a folder on the host system. A volume gets connected to your
application container and exists even when your application
container is not running.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="the-cross-compilation-workflow"&gt;
&lt;h2&gt;The cross-compilation workflow&lt;/h2&gt;
&lt;p&gt;Now that we have established the essential background to this project,
let's look at the cross-compilation workflow. Below is a picture that
provides a sense of the entire process, moving in general from
left-to-right.&lt;/p&gt;
&lt;img alt="The cross-compilation workflow" class="align-center" src="http://kmdouglass.github.io/images/mm_docker_workflow.png"&gt;
&lt;p&gt;The process involves two Docker containers: one for building
Micro-Manager and the other for running the application. The build
dependencies and the QEMU emulator are both located inside the build
container, having been specified when its image was created. These
allow us to compile Micro-Manager for the ARM architecture.  The
source code is connected to the build container as a &lt;em&gt;bind mount&lt;/em&gt;,
which is a folder from the host workstation that is mounted inside the
build container when it is run.&lt;/p&gt;
&lt;p&gt;Once the libraries are compiled, they are installed into a folder
inside the bind mount so that the host system will have access to them
after the build container closes. Next, the compiled libraries are
copied directly into an image that defines the application
container. This image defines only the essential run-time requirements
for running Micro-Manager and nothing else. The application image is
stored on the registry server which I set up on my local network. This
makes it easy for the Raspberry Pi to download the latest image and
run the Micro-Manager application container whenever I make changes.&lt;/p&gt;
&lt;p&gt;An important aspect of this workflow is how the data is passed between
the systems and containers. Unlike what you will find in many
introductory tutorials on Docker, I do not add the Micro-Manager
source code directly to the build image/containers but instead use a
bind mount. The reason for this is that the source code and 3rd party
libraries are quite large, about 8 GB in total. By using a bind mount,
I avoid needless copying of this data. Another reason for using a bind
mount is that the source code will change frequently during
development. If I add the source code to the image, then I will have
to recreate the image every time the source code changes.&lt;/p&gt;
&lt;p&gt;Once the libraries are built, I directly copy them into the
application image because they are much, much smaller than the source
code. I also want the code stored directly in the image so that the
application image is all the Raspberry Pi needs to run the
program. The image is stored in my local &lt;a class="reference external" href="https://docs.docker.com/registry/"&gt;Docker registry&lt;/a&gt; server so that once I push an
updated image to the server, the Raspberry Pi can download it and use
it immediately.&lt;/p&gt;
&lt;div class="section" id="step-0-prerequisites"&gt;
&lt;h3&gt;Step 0: Prerequisites&lt;/h3&gt;
&lt;p&gt;I am going to assume that you already have installed Docker. (If not,
follow &lt;a class="reference external" href="https://docs.docker.com/install/"&gt;these directions&lt;/a&gt;.) I am
also going to assume that you are somewhat familiar with how to work
on a Linux system. The Raspberry Pi runs Linux, so you probably
wouldn't be here if you didn't already know at least a little.&lt;/p&gt;
&lt;p&gt;For this article, I am working with these versions of Docker and
Ubuntu on my host workstation.:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
kmdouglass@xxxxx:~$ uname -a
Linux xxxxx 4.13.0-39-generic #44~16.04.1-Ubuntu SMP Thu Apr 5 16:43:10 UTC 2018 x86_64 x86_64
x86_64 GNU/Linux

kmdouglass@xxxxx:~$ docker version
Client:
 Version:      18.03.1-ce
 API version:  1.37
 Go version:   go1.9.5
 Git commit:   9ee9f40
 Built:        Thu Apr 26 07:17:20 2018
 OS/Arch:      linux/amd64
 Experimental: false
 Orchestrator: swarm

Server:
 Engine:
  Version:      18.03.1-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.5
  Git commit:   9ee9f40
  Built:        Thu Apr 26 07:15:30 2018
  OS/Arch:      linux/amd64
  Experimental: false
&lt;/pre&gt;
&lt;p&gt;Finally, below is how my project directory structure is laid out.:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
kmdouglass@xxxxx:~/src/alphapi/docker$ tree -L 2
.
└── rpi-micromanager
    ├── 2.0-python
    │   ├── build
    │   └── Dockerfile
    └── build
        ├── build
        ├── Dockerfile
        ├── run
        └── setup
&lt;/pre&gt;
&lt;p&gt;I have two folders; build, which contains the files for the build
container, and 2.0-python, which contains the files for creating the
Micro-Manager application container. (In my case, I am going to build
the Python wrapper for Micro-Manager 2.0.) Inside each folder are the
scripts and Dockerfiles that execute the various steps of the
workflow.&lt;/p&gt;
&lt;p&gt;The final prerequisite is to register QEMU with the Docker build
agent. First, install a few packages for QEMU. On Ubuntu, this looks
like&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_deacfa1a9a25439a970acfc38f97963f-1"&gt;&lt;/a&gt;$ sudo apt update
&lt;a name="rest_code_deacfa1a9a25439a970acfc38f97963f-2"&gt;&lt;/a&gt;$ sudo install qemu qemu-user-static qemu-user binfmt-support
&lt;/pre&gt;&lt;p&gt;Finally, register the build agent with the command:&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_e8b8d4d4c8e540d59c38b8017332baba-1"&gt;&lt;/a&gt;$ docker run --rm --privileged multiarch/qemu-user-static:register --reset
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="step-1-create-the-build-image"&gt;
&lt;h3&gt;Step 1: Create the build image&lt;/h3&gt;
&lt;p&gt;Inside the build folder, I have a file called Dockerfile. Here are its
contents.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-1"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Copyright (C) 2018 Kyle M. Douglass&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-2"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-3"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Defines a build environment for Micro-Manager on the Raspberry Pi.&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-4"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-5"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Usage: docker build \&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-6"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#          -t NAME:TAG \&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-7"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#         .&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-8"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-9"&gt;&lt;/a&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-10"&gt;&lt;/a&gt;FROM resin/raspberrypi3-debian:stretch
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-11"&gt;&lt;/a&gt;MAINTAINER Kyle M. Douglass &amp;lt;kyle.m.douglass@gmail.com&amp;gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-12"&gt;&lt;/a&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-13"&gt;&lt;/a&gt;RUN &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"cross-build-start"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-14"&gt;&lt;/a&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-15"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Get the build dependencies.&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-16"&gt;&lt;/a&gt;RUN apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get -y install --no-install-recommends &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-17"&gt;&lt;/a&gt;autoconf &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-18"&gt;&lt;/a&gt;automake &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-19"&gt;&lt;/a&gt;build-essential &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-20"&gt;&lt;/a&gt;git &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-21"&gt;&lt;/a&gt;libatlas-base-dev &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-22"&gt;&lt;/a&gt;libboost-dev &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-23"&gt;&lt;/a&gt;libboost-all-dev &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-24"&gt;&lt;/a&gt;libtool &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-25"&gt;&lt;/a&gt;patch &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-26"&gt;&lt;/a&gt;pkg-config &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-27"&gt;&lt;/a&gt;python3-dev &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-28"&gt;&lt;/a&gt;python3-pip &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-29"&gt;&lt;/a&gt;python3-setuptools &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-30"&gt;&lt;/a&gt;python3-wheel &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-31"&gt;&lt;/a&gt;swig &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-32"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get clean &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm -rf /var/lib/apt/lists/* &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-33"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pip3 install numpy
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-34"&gt;&lt;/a&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-35"&gt;&lt;/a&gt;RUN &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"cross-build-end"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-36"&gt;&lt;/a&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-37"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Set up the mount point for the source files and setup script.&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-38"&gt;&lt;/a&gt;ADD setup /micro-manager/
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-39"&gt;&lt;/a&gt;VOLUME /micro-manager/src
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-40"&gt;&lt;/a&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-41"&gt;&lt;/a&gt;WORKDIR /micro-manager/src
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-42"&gt;&lt;/a&gt;ENTRYPOINT &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"/sbin/tini"&lt;/span&gt;, &lt;span class="s2"&gt;"-s"&lt;/span&gt;, &lt;span class="s2"&gt;"--"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;a name="rest_code_c0a4d4086a554bd99c3d67b732f508f6-43"&gt;&lt;/a&gt;CMD &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"/micro-manager/setup"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;A Dockerfile defines the steps in building an image -- in this case,
the build image. Let's break this file down into pieces. In the first
two lines that follow the comments, I specify that my image is based
on the resin/raspberrypi3-debian:stretch image and that I am the
maintainer.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_6f6100ac8b7b4501961496830d326e59-1"&gt;&lt;/a&gt;FROM resin/raspberrypi3-debian:stretch
&lt;a name="rest_code_6f6100ac8b7b4501961496830d326e59-2"&gt;&lt;/a&gt;MAINTAINER Kyle M. Douglass &amp;lt;kyle.m.douglass@gmail.com&amp;gt;
&lt;/pre&gt;&lt;p&gt;Images from &lt;a class="reference external" href="https://hub.docker.com/u/resin/"&gt;Resin&lt;/a&gt; are freely
available and already have the QEMU emulator installed. Next, I
specify what commands should be run for the ARM architecture. Any
commands located between &lt;tt class="docutils literal"&gt;RUN [ &lt;span class="pre"&gt;"cross-build-start"&lt;/span&gt; ]&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;RUN [
&lt;span class="pre"&gt;"cross-build-end"&lt;/span&gt; ]&lt;/tt&gt; will be run using the emulator. Inside these two
commands, I install the build dependencies for Micro-Manager using
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;apt-get&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;pip&lt;/tt&gt;. (These are just standard commands for
installing software on Debian/Ubuntu Linux machines and from PyPI,
respectively.)&lt;/p&gt;
&lt;p&gt;After the installation of the requirements completes, I add the setup
script to the folder /micro-manager inside the image with the &lt;tt class="docutils literal"&gt;ADD
setup &lt;span class="pre"&gt;/micro-manager/&lt;/span&gt;&lt;/tt&gt; command. The setup script contains the
commands that will actually compile Micro-Manager. I then define a
mount point for the source code with &lt;tt class="docutils literal"&gt;VOLUME
&lt;span class="pre"&gt;/micro-manager/src&lt;/span&gt;&lt;/tt&gt;. &lt;strong&gt;It's important to realize here that you do not
mount volumes inside images, you mount volumes inside containers.&lt;/strong&gt;
This command is just telling the image to expect a folder to be
mounted at this location when the container is run.&lt;/p&gt;
&lt;p&gt;The last three lines set the working directory, the entrypoint and the
default container command, respectively.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_562074e3cfad486b82873bea18b77684-1"&gt;&lt;/a&gt;WORKDIR /micro-manager/src
&lt;a name="rest_code_562074e3cfad486b82873bea18b77684-2"&gt;&lt;/a&gt;ENTRYPOINT &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"/sbin/tini"&lt;/span&gt;, &lt;span class="s2"&gt;"-s"&lt;/span&gt;, &lt;span class="s2"&gt;"--"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;a name="rest_code_562074e3cfad486b82873bea18b77684-3"&gt;&lt;/a&gt;CMD &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"/micro-manager/setup"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;This specific entrypoint tells Docker that any containers built from
this image should first run Tini, which is a lightweight init system
for Docker containers. If you do not specify Tini as the entry point,
then it will not be able to reap zombies. (I don't know what this
means exactly, but it sounds cool and you can read about it here:
&lt;a class="reference external" href="https://github.com/krallin/tini"&gt;https://github.com/krallin/tini&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;By default, the container will run the setup script, but, since I used
the &lt;tt class="docutils literal"&gt;CMD&lt;/tt&gt; directive, this can be overriden in case we need to
perform some manual steps. Roughly speaking, you can think of the
entrypoint as the command that can not be overridden and the CMD
command as the one that can be. In other words, Tini will always be
executed when containers created from this image are launched, whereas
you can choose not to run the setup script but instead to enter the
container through a Bash shell, for example.&lt;/p&gt;
&lt;p&gt;To build the image, I use the following build script located in the
same directory as the Dockerfile for convenience.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_3ac75315a8d942d49bc70301c60b9981-1"&gt;&lt;/a&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;a name="rest_code_3ac75315a8d942d49bc70301c60b9981-2"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Copyright (C) 2018 Kyle M. Douglass&lt;/span&gt;
&lt;a name="rest_code_3ac75315a8d942d49bc70301c60b9981-3"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_3ac75315a8d942d49bc70301c60b9981-4"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Usage: ./build&lt;/span&gt;
&lt;a name="rest_code_3ac75315a8d942d49bc70301c60b9981-5"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_3ac75315a8d942d49bc70301c60b9981-6"&gt;&lt;/a&gt;
&lt;a name="rest_code_3ac75315a8d942d49bc70301c60b9981-7"&gt;&lt;/a&gt;docker build &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_3ac75315a8d942d49bc70301c60b9981-8"&gt;&lt;/a&gt;       -t localhost:5000/rpi-micromanager:build &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_3ac75315a8d942d49bc70301c60b9981-9"&gt;&lt;/a&gt;       .
&lt;/pre&gt;&lt;p&gt;By using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-t&lt;/span&gt; &lt;span class="pre"&gt;localhost:5000/rpi-micromanager:build&lt;/span&gt;&lt;/tt&gt; argument I am
giving the image a name of &lt;em&gt;rpi-micromanager&lt;/em&gt;, a tag of &lt;em&gt;build&lt;/em&gt;, and
specifying that I will eventually host this image on my local registry
server (localhost) on port 5000.&lt;/p&gt;
&lt;p&gt;In case you are wondering about the contents of the setup script,
don't worry. I'll explain it in the next section.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="step-2-compile-micro-manager"&gt;
&lt;h3&gt;Step 2: Compile Micro-Manager&lt;/h3&gt;
&lt;p&gt;After the image is built, I create a container and use it to compile
Micro-Manager. For this, I use the run script in the build directory.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-1"&gt;&lt;/a&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-2"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Copyright (C) 2018 Kyle M. Douglass&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-3"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-4"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Usage: ./run DIR CONFIGURE&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-5"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-6"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# DIR is the parent folder containing the micro-manager Git&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-7"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# repository, the 3rdpartypublic Subversion repository, and any&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-8"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# additional build resources.&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-9"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-10"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# If CONFIGURE=true, the build system is remade and the configure&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-11"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# script is rerun before running 'make' and 'make install'. If&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-12"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# CONFIGURE=false, only 'make' and 'make install' are run.&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-13"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-14"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# The compiled program files are stored in a bind mount volume so that&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-15"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# they may be copied into the deployment container.&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-16"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-17"&gt;&lt;/a&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-18"&gt;&lt;/a&gt;&lt;span class="nv"&gt;src_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-19"&gt;&lt;/a&gt;&lt;span class="nv"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/micro-manager/setup &lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-20"&gt;&lt;/a&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-21"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Remove the build artifacts from previous builds.&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-22"&gt;&lt;/a&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-23"&gt;&lt;/a&gt;    rm -rf &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;src_dir&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/build &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-24"&gt;&lt;/a&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-25"&gt;&lt;/a&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-26"&gt;&lt;/a&gt;docker run --rm &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-27"&gt;&lt;/a&gt;       -v &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;src_dir&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;:/micro-manager/src &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-28"&gt;&lt;/a&gt;       --name mm-build &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-29"&gt;&lt;/a&gt;       localhost:5000/rpi-micromanager:build &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_9aac600ac9774ed1b1899fa4c2e3c8fb-30"&gt;&lt;/a&gt;       &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cmd&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The script takes two arguments. The first is the path to the folder
containing all the source code (see below for details). The second
argument is either &lt;strong&gt;true&lt;/strong&gt; or &lt;strong&gt;false&lt;/strong&gt;. (It can actually be
anything, but it will only compile Micro-Manager if either &lt;strong&gt;true&lt;/strong&gt; or
&lt;strong&gt;false&lt;/strong&gt; are provided.) If true, the full build process is run,
including setting up the configure script; if false, only make and
make install are run, which should recompile and install only recently
updated files.&lt;/p&gt;
&lt;p&gt;The run script uses the -v argument to &lt;tt class="docutils literal"&gt;docker run&lt;/tt&gt; to mount the
source directory into the container at the point specified by the
&lt;tt class="docutils literal"&gt;VOLUME&lt;/tt&gt; command in the Dockerfile. The directory layout on my host
file system for the source directory looks like this:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
kmdouglass@xxxxx:/media/kmdouglass/Data/micro-manager$ tree -L 1
.
├── 3rdpartypublic
├── micro-manager
└── patches
&lt;/pre&gt;
&lt;p&gt;The patches folder is not necessary and only there to fix &lt;a class="reference external" href="https://github.com/micro-manager/micro-manager/pull/613"&gt;a bug&lt;/a&gt; in the
WieneckeSinscke device adapter. (This bug may be fixed by now.)
3rdpartypublic is the large Subversion repository of all the required
software to build Micro-Manager, and micro-manager is the &lt;a class="reference external" href="https://github.com/micro-manager/micro-manager"&gt;cloned
GitHub repository&lt;/a&gt;. Prior to building,
I checkout the mm2 branch because I am interested in developing my
application for Micro-Manager 2.0.&lt;/p&gt;
&lt;p&gt;The setup script that is run inside the container and mentioned in the
previous section looks like this.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-1"&gt;&lt;/a&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-2"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-3"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# # Copyright (C) 2018 Kyle M. Douglass&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-4"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-5"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Builds Micro-Manager.&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-6"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-7"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Usage: ./setup CONFIGURE&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-8"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-9"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# If CONFIGURE=true, the build system is remade and the configure&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-10"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# script is rerun before running 'make' and 'make install'. If&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-11"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# CONFIGURE=false, only 'make' and 'make install' or run.&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-12"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-13"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Kyle M. Douglass, 2018&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-14"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-15"&gt;&lt;/a&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-16"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Move into the source directory.&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-17"&gt;&lt;/a&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; micro-manager
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-18"&gt;&lt;/a&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-19"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Undo any previous patches.&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-20"&gt;&lt;/a&gt;git checkout -- DeviceAdapters/WieneckeSinske/CAN29.cpp
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-21"&gt;&lt;/a&gt;git checkout -- DeviceAdapters/WieneckeSinske/WieneckeSinske.cpp
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-22"&gt;&lt;/a&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-23"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Patch the broken WieneckeSinske device adapter.&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-24"&gt;&lt;/a&gt;patch DeviceAdapters/WieneckeSinske/CAN29.cpp &amp;lt; ../patches/CAN29.cpp.diff &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-25"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; patch DeviceAdapters/WieneckeSinske/WieneckeSinske.cpp &amp;lt; ../patches/WieneckeSinske.cpp.diff
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-26"&gt;&lt;/a&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-27"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Compile MM2.&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-28"&gt;&lt;/a&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-29"&gt;&lt;/a&gt;    &lt;span class="c1"&gt;# Remake the entire build system, then compile from scratch.&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-30"&gt;&lt;/a&gt;    ./autogen.sh
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-31"&gt;&lt;/a&gt;    &lt;span class="nv"&gt;PYTHON&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/usr/bin/python3"&lt;/span&gt; ./configure &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-32"&gt;&lt;/a&gt;        --prefix&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/micro-manager/src/build"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-33"&gt;&lt;/a&gt;        --with-python&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/usr/include/python3.5"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-34"&gt;&lt;/a&gt;        --with-boost-libdir&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/usr/lib/arm-linux-gnueabihf"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-35"&gt;&lt;/a&gt;        --with-boost&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/usr/include/boost"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-36"&gt;&lt;/a&gt;        --disable-java-app &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-37"&gt;&lt;/a&gt;        --disable-install-dependency-jars &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-38"&gt;&lt;/a&gt;        --with-java&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"no"&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-39"&gt;&lt;/a&gt;    make
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-40"&gt;&lt;/a&gt;    make install
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-41"&gt;&lt;/a&gt;    chmod -R a+w /micro-manager/src/build
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-42"&gt;&lt;/a&gt;&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-43"&gt;&lt;/a&gt;    &lt;span class="c1"&gt;# Only recompile changed source files.&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-44"&gt;&lt;/a&gt;    make
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-45"&gt;&lt;/a&gt;    make install
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-46"&gt;&lt;/a&gt;    chmod -R a+w /micro-manager/src/build
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-47"&gt;&lt;/a&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-48"&gt;&lt;/a&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; : Unrecognized argument."&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-49"&gt;&lt;/a&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Pass \"true\" to run the full build process."&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-50"&gt;&lt;/a&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Pass \"false\" to run only \"make\" and \"make install\"."&lt;/span&gt;
&lt;a name="rest_code_c4bdae05ce3949a29a977ba64ad474a1-51"&gt;&lt;/a&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Most important in this script is the call to &lt;tt class="docutils literal"&gt;configure&lt;/tt&gt;. You can
see that the compiled libraries and Python wrapper will be written to
the build folder inside the mounted directory. This gives the host
file system access to the compiled artifacts after the container has
stopped.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="step-3-build-the-application-image"&gt;
&lt;h3&gt;Step 3: Build the application image&lt;/h3&gt;
&lt;p&gt;Once the libraries are compiled, we can add them to an application
image that contains only the essentials for running Micro-Manager.&lt;/p&gt;
&lt;p&gt;For this, I use a separate Dockerfile inside the 2.0-python
directory.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-1"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Copyright (C) 2018 Kyle M. Douglass&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-2"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-3"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Builds the Micro-Manager 2.0 Python wrapper for the Raspberry Pi.&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-4"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-5"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Usage: docker build \&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-6"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#          -t NAME:TAG \&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-7"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#          .&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-8"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-9"&gt;&lt;/a&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-10"&gt;&lt;/a&gt;FROM resin/raspberrypi3-debian:stretch
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-11"&gt;&lt;/a&gt;MAINTAINER Kyle M. Douglass &amp;lt;kyle.m.douglass@gmail.com&amp;gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-12"&gt;&lt;/a&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-13"&gt;&lt;/a&gt;RUN &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"cross-build-start"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-14"&gt;&lt;/a&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-15"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Install the run-time dependencies.&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-16"&gt;&lt;/a&gt;RUN apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get -y install --no-install-recommends &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-17"&gt;&lt;/a&gt;    libatlas-base-dev &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-18"&gt;&lt;/a&gt;    libboost-all-dev &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-19"&gt;&lt;/a&gt;    python3-pip &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-20"&gt;&lt;/a&gt;    python3-setuptools &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-21"&gt;&lt;/a&gt;    python3-wheel &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-22"&gt;&lt;/a&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pip3 install numpy &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-23"&gt;&lt;/a&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get clean &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm -rf /var/lib/apt/lists/*
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-24"&gt;&lt;/a&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-25"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Copy in the Micro-Manager source files.&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-26"&gt;&lt;/a&gt;RUN useradd -ms /bin/bash micro-manager
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-27"&gt;&lt;/a&gt;WORKDIR /home/micro-manager/app
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-28"&gt;&lt;/a&gt;COPY --chown&lt;span class="o"&gt;=&lt;/span&gt;micro-manager:micro-manager . .
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-29"&gt;&lt;/a&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-30"&gt;&lt;/a&gt;RUN &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"cross-build-end"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-31"&gt;&lt;/a&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-32"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Final environment configuration.&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-33"&gt;&lt;/a&gt;USER micro-manager:micro-manager
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-34"&gt;&lt;/a&gt;ENV PYTHONPATH /home/micro-manager/app/lib/micro-manager
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-35"&gt;&lt;/a&gt;ENTRYPOINT &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"/sbin/tini"&lt;/span&gt;, &lt;span class="s2"&gt;"-s"&lt;/span&gt;, &lt;span class="s2"&gt;"--"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;a name="rest_code_d2c39a585a2c4f18b05c576e91c7b9e5-36"&gt;&lt;/a&gt;CMD &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"/usr/bin/python3"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;As before, I use a clean resin base image. However, this time I only
install the essential software to run Micro-Manager.&lt;/p&gt;
&lt;p&gt;After apt-getting and pip-installing everything, I create a new user
called &lt;strong&gt;micro-manager&lt;/strong&gt; and a new folder called &lt;strong&gt;app&lt;/strong&gt; inside this
user's home directory.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_429cf0806a154ad1830bf3a72e544697-1"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Copy in the Micro-Manager source files.&lt;/span&gt;
&lt;a name="rest_code_429cf0806a154ad1830bf3a72e544697-2"&gt;&lt;/a&gt;RUN useradd -ms /bin/bash micro-manager
&lt;a name="rest_code_429cf0806a154ad1830bf3a72e544697-3"&gt;&lt;/a&gt;WORKDIR /home/micro-manager/app
&lt;/pre&gt;&lt;p&gt;Next, I directly copy the compiled libraries into the image with the
COPY command.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_669f943f2dbd45fea1871087ea64446f-1"&gt;&lt;/a&gt;COPY --chown&lt;span class="o"&gt;=&lt;/span&gt;micro-manager:micro-manager . .
&lt;/pre&gt;&lt;p&gt;The two periods (.) mean that I copy the current host directory's
contents into the container's current working directory
(/home/micro-manager/app). What is the current host directory? Well,
as I explain below, I actually run this Dockerfile from inside the
&lt;strong&gt;build&lt;/strong&gt; folder that was created to hold the compiled libraries in
the previous step. But first, I'll end my explanation of the
Dockerfile by saying that I switch the USER so that I do not run the
container as root, add the library to the PYTHONPATH environment
variable, and setup the default command as the python3 interpreter.&lt;/p&gt;
&lt;p&gt;To build this image, I use the following build script.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_dc3a0e2e3f174899a0f46febdbac5215-1"&gt;&lt;/a&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;a name="rest_code_dc3a0e2e3f174899a0f46febdbac5215-2"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Copyright (C) 2018 Kyle M. Douglass&lt;/span&gt;
&lt;a name="rest_code_dc3a0e2e3f174899a0f46febdbac5215-3"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_dc3a0e2e3f174899a0f46febdbac5215-4"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Usage: ./build DIR&lt;/span&gt;
&lt;a name="rest_code_dc3a0e2e3f174899a0f46febdbac5215-5"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_dc3a0e2e3f174899a0f46febdbac5215-6"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# DIR is the root directory containing the Micro-Manager build&lt;/span&gt;
&lt;a name="rest_code_dc3a0e2e3f174899a0f46febdbac5215-7"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# artifacts. These artifacts will be added to the Docker image.&lt;/span&gt;
&lt;a name="rest_code_dc3a0e2e3f174899a0f46febdbac5215-8"&gt;&lt;/a&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;a name="rest_code_dc3a0e2e3f174899a0f46febdbac5215-9"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc3a0e2e3f174899a0f46febdbac5215-10"&gt;&lt;/a&gt;&lt;span class="nv"&gt;src_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;a name="rest_code_dc3a0e2e3f174899a0f46febdbac5215-11"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc3a0e2e3f174899a0f46febdbac5215-12"&gt;&lt;/a&gt;cp Dockerfile &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;src_dir&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;a name="rest_code_dc3a0e2e3f174899a0f46febdbac5215-13"&gt;&lt;/a&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;src_dir&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;a name="rest_code_dc3a0e2e3f174899a0f46febdbac5215-14"&gt;&lt;/a&gt;
&lt;a name="rest_code_dc3a0e2e3f174899a0f46febdbac5215-15"&gt;&lt;/a&gt;docker build &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_dc3a0e2e3f174899a0f46febdbac5215-16"&gt;&lt;/a&gt;       -t localhost:5000/rpi-micromanager:2.0-python &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_dc3a0e2e3f174899a0f46febdbac5215-17"&gt;&lt;/a&gt;       .
&lt;/pre&gt;&lt;p&gt;This script takes one argument, which is the &lt;strong&gt;build&lt;/strong&gt; directory
containing the compiled source code. The script first copies the
Dockerfile into this directory and then changes into it with the cd
command. (This explains the two periods (.) in the COPY command in the
Dockerfile.)&lt;/p&gt;
&lt;p&gt;Finally, I build the image and give it a name of
localhost:5000/rpi-micromanager:2.0-python.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="step-4-add-the-image-to-the-local-registry-server"&gt;
&lt;h3&gt;Step 4: Add the image to the local registry server&lt;/h3&gt;
&lt;p&gt;Now we need a way to get the image from the workstation onto the
Raspberry Pi. Of course, I could manually transfer the file with a USB
stick or possibly use ssh, but what if I have multiple Pi's? This
process could become cumbersome. Docker provides a few ways to push
and pull images across a network. The most obvious is &lt;a class="reference external" href="https://hub.docker.com/"&gt;Dockerhub&lt;/a&gt;, a site for freely sharing images. For the
moment I don't want to use Dockerhub, though, because I have not yet
checked all the software licenses and am unsure as to what my rights
are for putting an image with Micro-Manager software on a public
repository.&lt;/p&gt;
&lt;p&gt;A better option, especially for testing, is to use a local registry
server. This server operates only on my home network and already
allows my workstation and Pi's to communicate with one
another. Following the &lt;a class="reference external" href="https://docs.docker.com/registry/deploying/"&gt;official registry documentation&lt;/a&gt; and &lt;a class="reference external" href="http://zacharykeeton.com/docker-private-registry/"&gt;this blog post by
Zachary Keeton&lt;/a&gt;,
I managed to setup the registry as follows.&lt;/p&gt;
&lt;div class="section" id="host-setup"&gt;
&lt;h4&gt;Host setup&lt;/h4&gt;
&lt;p&gt;First, we need to setup a transport layer security (TLS)
certificate. It's possible to run the server without one if you don't
expect your network to be attacked, but it's good practice so let's
create one.&lt;/p&gt;
&lt;p&gt;To do this, I edit the /etc/ssl/openssl.cnf file and add the following
to the top of the [ v3_ca ] section.:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
subjectAltName = IP:192.168.XXX.XXX
&lt;/pre&gt;
&lt;p&gt;where the IP address is the address of the workstation on the
network. Next, I actually create the certificate. I make a directory
called certs inside my workstation home directory and then use openssl
to make the cerficate. During the prompts, I press ENTER at every step
except the FQDN (fully qualified domain name). For the FQDN, I enter
the same IP address as above.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_86887feb6b394f85a6cb2b2087c05d36-1"&gt;&lt;/a&gt;mkdir certs
&lt;a name="rest_code_86887feb6b394f85a6cb2b2087c05d36-2"&gt;&lt;/a&gt;openssl req -newkey rsa:4096 -nodes -sha256 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_86887feb6b394f85a6cb2b2087c05d36-3"&gt;&lt;/a&gt;-keyout certs/domain.key -x509 -days &lt;span class="m"&gt;365&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_86887feb6b394f85a6cb2b2087c05d36-4"&gt;&lt;/a&gt;-config /etc/ssl/openssl.cnf -out certs/domain.crt
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;I had to add the ``-config /etc/ssl/openssl.cnf`` argument for the
subject alternative name to be added to the certificate.&lt;/strong&gt; This part
was tricky, because if this argument is not included, then the key
generation step will use some other .cnf file (I am not sure
which). This results in the following SAN error when attemptingt to
connect to the registry.:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
cannot validate certificate for 192.168.XXX.XXX because it doesn't contain any IP SANs
&lt;/pre&gt;
&lt;p&gt;After the domain.key and domain.crt files have been created, I run the
official registry server container. (See how handy Docker containers
are? There's no messy installation beyond grabbing the container.)&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_0a9896e55c0d4f90aeeca6488c13fa6a-1"&gt;&lt;/a&gt;docker run -d -p &lt;span class="m"&gt;5000&lt;/span&gt;:5000 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_0a9896e55c0d4f90aeeca6488c13fa6a-2"&gt;&lt;/a&gt;  --restart&lt;span class="o"&gt;=&lt;/span&gt;always &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_0a9896e55c0d4f90aeeca6488c13fa6a-3"&gt;&lt;/a&gt;  --name registry &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_0a9896e55c0d4f90aeeca6488c13fa6a-4"&gt;&lt;/a&gt;  -v &lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;/certs:/certs &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_0a9896e55c0d4f90aeeca6488c13fa6a-5"&gt;&lt;/a&gt;  -e &lt;span class="nv"&gt;REGISTRY_HTTP_TLS_CERTIFICATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/certs/domain.crt &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_0a9896e55c0d4f90aeeca6488c13fa6a-6"&gt;&lt;/a&gt;  -e &lt;span class="nv"&gt;REGISTRY_HTTP_TLS_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/certs/domain.key &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_0a9896e55c0d4f90aeeca6488c13fa6a-7"&gt;&lt;/a&gt;  registry:2
&lt;/pre&gt;&lt;p&gt;If the registry:2 image is not already downloaded, then it will be
downloaded for automatically when running the container. Note that
the -p 5000:5000 argument indicates that the server is using port 5000
on both the host system and inside the container. Note also that the
certs directory is relative to the current directory because I use the
($pwd) command. You can change this to an absolute path if you wish on
your setup.&lt;/p&gt;
&lt;p&gt;Let's go ahead and push the application image to the server now that
it's running.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_9f2efb97cc1f4405b31df75762cf0ccd-1"&gt;&lt;/a&gt;docker push localhost:5000/rpi-micromanager:2.0-python
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="setup-the-pi"&gt;
&lt;h4&gt;Setup the Pi&lt;/h4&gt;
&lt;p&gt;Now, startup the Pi. I will assume that you have &lt;a class="reference external" href="https://www.raspberrypi.org/blog/docker-comes-to-raspberry-pi/"&gt;already installed
Docker&lt;/a&gt; on
it and know how to communicate with it via ssh and copy files to it
using scp.&lt;/p&gt;
&lt;p&gt;I copy the certificate from the host with scp.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_01f2057272c64a55a7dc30a09662f278-1"&gt;&lt;/a&gt;sudo mkdir -p /etc/docker/certs.d/192.168.XXX.XXX:5000/
&lt;a name="rest_code_01f2057272c64a55a7dc30a09662f278-2"&gt;&lt;/a&gt;sudo scp kmdouglass@192.168.XXX.XXX:/home/kmdouglass/certs/domain.crt /etc/docker/certs.d/192.168.XXX.XXX:5000/ca.crt
&lt;/pre&gt;&lt;p&gt;The IP address that I am using is the one to the machine where the
registry server is running. After this step, I make the operating
system trust the certificate.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_b992be5945ec448c99eb26412ad3fcd8-1"&gt;&lt;/a&gt;sudo scp kmdouglass@192.168.XXX.XXX:/home/kmdouglass/certs/domain.crt /usr/local/share/ca-certificates/192.168.XXX.XXX.crt
&lt;a name="rest_code_b992be5945ec448c99eb26412ad3fcd8-2"&gt;&lt;/a&gt;sudo update-ca-certifications
&lt;/pre&gt;&lt;p&gt;Finally, I restart the Docker daemon.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_2ad10e9d31d944548082cd85d6f25f6d-1"&gt;&lt;/a&gt;sudo service docker restart
&lt;/pre&gt;&lt;p&gt;If everything is working, then I should be able to pull the image from
your network's registry server.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_f9dbff5d6425426489523f7e12278aab-1"&gt;&lt;/a&gt;docker pull &lt;span class="m"&gt;192&lt;/span&gt;.168.XXX.XXX:5000/rpi-micromanager:python2.0
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="step-5-run-micro-manager"&gt;
&lt;h3&gt;Step 5: Run Micro-Manager!&lt;/h3&gt;
&lt;p&gt;And now the moment of truth: running the application container. Since
it's setup to run Python automatically, I use a pretty simple &lt;tt class="docutils literal"&gt;docker
run&lt;/tt&gt; command.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a name="rest_code_44303c2f70dc4c699fe02dd7140e1c76-1"&gt;&lt;/a&gt;docker run -it --rm &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_44303c2f70dc4c699fe02dd7140e1c76-2"&gt;&lt;/a&gt;     --name micro-manager &lt;span class="se"&gt;\&lt;/span&gt;
&lt;a name="rest_code_44303c2f70dc4c699fe02dd7140e1c76-3"&gt;&lt;/a&gt;     &lt;span class="m"&gt;192&lt;/span&gt;.168.XXX.XXX:5000/rpi-micromanager:2.0-python
&lt;/pre&gt;&lt;p&gt;I verify that the Micro-Manager Python wrapper is working by trying to
import it and run &lt;a class="reference external" href="https://micro-manager.org/wiki/Using_the_Micro-Manager_python_library"&gt;a few basic commands&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a name="rest_code_5bd277414f21415497aef665e01aa4dc-1"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;MMCorePy&lt;/span&gt;
&lt;a name="rest_code_5bd277414f21415497aef665e01aa4dc-2"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mmc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MMCorePy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CMMCore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a name="rest_code_5bd277414f21415497aef665e01aa4dc-3"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mmc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getVersionInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;If these work without error, then congratulations! You're now ready to
start building your embedded microscopy system ;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="step-6-running-the-whole-process"&gt;
&lt;h3&gt;Step 6: Running the whole process&lt;/h3&gt;
&lt;p&gt;The beauty of having scripted all these steps is that the full
workflow may be executed quite simply. From the host system's build
folder, run:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
kmdouglass@xxxxx:~/src/alphapi/docker/rpi-micromanager/build$ ./build
kmdouglass@xxxxx:~/src/alphapi/docker/rpi-micromanager/build$ ./run /path/to/source true
&lt;/pre&gt;
&lt;p&gt;From the 2.0-python folder:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
kmdouglass@xxxxx:~/src/alphapi/docker/rpi-micromanager/2.0-python ./build /path/to/source/artifacts
kmdouglass@xxxxx:~$ docker push localhost:5000/rpi-micromanager:2.0-python
&lt;/pre&gt;
&lt;p&gt;And from the Raspberry Pi:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
pi@yyyyy:~$ docker pull 192.168.XXX.XXX:5000/rpi-micromanager:2.0-python
pi@yyyyy:~$ docker run -it --rm \
                   --name micro-manager \
                   192.168.XXX.XXX:5000/rpi-micromanager:2.0-python
&lt;/pre&gt;
&lt;p&gt;Hopefully this is enough to get you started building Micro-Manager for
the Raspberry Pi with Docker. Though I focused on Micro-Manager, the
workflow should be generally applicable to any large scale project in
which you want to isolate the build environment from the host machine.&lt;/p&gt;
&lt;p&gt;If you have any questions, just leave them in the comments. Happy
programming!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;</description><category>docker</category><category>micro-manager</category><category>raspberry pi</category><guid>http://kmdouglass.github.io/posts/how-i-built-a-cross-compilation-workflow-for-the-raspberry-pi/</guid><pubDate>Sun, 29 Apr 2018 10:10:26 GMT</pubDate></item></channel></rss>