<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title></title>
  <subtitle></subtitle>
  <id>https://www.endpointdev.com/blog/tags/c/</id>
  <link href="https://www.endpointdev.com/blog/tags/c/"/>
  <link href="https://www.endpointdev.com/blog/tags/c/" rel="self"/>
  <updated>2018-04-16T00:00:00+00:00</updated>
  <author>
    <name>End Point Dev</name>
  </author>
  
    <entry>
      <title>Using FFI in Ruby</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2018/04/ffi-in-ruby/"/>
      <id>https://www.endpointdev.com/blog/2018/04/ffi-in-ruby/</id>
      <published>2018-04-16T00:00:00+00:00</published>
      <author>
        <name>Kamil Ciemniewski</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2018/04/ffi-in-ruby/37496475781_1384a35df9_o-crop.jpg&#34; alt=&#34;Photo of pipes&#34; /&gt;&lt;br /&gt;
&lt;small&gt;&lt;a href=&#34;https://www.flickr.com/photos/amob_sa/37496475781&#34;&gt;Photo from AMOB&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Ruby for many years has been proving to be an amazing language. It’s one of the most popular for creating web applications but also DevOps / systems administration tools.&lt;/p&gt;
&lt;p&gt;It seems that languages are naturally finding their own niches. For Ruby it’s what I listed above, while Python seems to work well for computer vision and machine learning.&lt;/p&gt;
&lt;p&gt;For performance reasons, some code should never be coded in either one. Topic boundaries are being crossed typically though. You might be working on the web app that does some high performance math in the background. To marry the two worlds, people were successful with creating compiled “extensions”. These extensions are typically coded in C. Both languages along with their interpreters are able to use those using native-to-language constructs.&lt;/p&gt;
&lt;p&gt;One good example of this is the great &lt;code&gt;numpy&lt;/code&gt; package. It brings high-performance linear algebra constructs that would be impossible to code in pure Python with the same performance.&lt;/p&gt;
&lt;p&gt;In the Ruby land, a similar example is the &lt;code&gt;nokogiri&lt;/code&gt; gem. It allows very fast XML / HTML processing thanks to the core of its functionality being coded in C.&lt;/p&gt;
&lt;p&gt;You might also be working on a Ruby app having a need for a functionality that has already been written as a library with C interface available. One way to use it would be to create an extension that would operate on those external C functions. This involves quite a lot of prep-work though. The &lt;a href=&#34;http://guides.rubygems.org/gems-with-extensions/&#34;&gt;RubyGems guides&lt;/a&gt; describe the process in detail.&lt;/p&gt;
&lt;p&gt;There is one more option and I’m about to show you what it is.&lt;/p&gt;
&lt;h3 id=&#34;referencing-external-functions-directly&#34;&gt;Referencing external functions directly&lt;/h3&gt;
&lt;p&gt;FFI stands for “Foreign Function Interface”. Most languages have a way to operate with external code (written in another language). The interface for doing so is what’s called FFI. Examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://wiki.haskell.org/FFI_Introduction&#34;&gt;Docs on FFI in Haskell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cffi.readthedocs.io/en/latest/&#34;&gt;Docs on FFI in Python&lt;/a&gt; via the &lt;code&gt;cffi&lt;/code&gt; package&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/ffi/ffi/wiki&#34;&gt;Docs on FFI in Ruby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://doc.rust-lang.org/book/ffi.html&#34;&gt;Docs on FFI in Rust&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this article, we’re interested in using &lt;code&gt;FFI&lt;/code&gt; in Ruby.&lt;/p&gt;
&lt;p&gt;No matter what the host language, the usage pattern is always the same:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Define what external library you want to link with&lt;/li&gt;
&lt;li&gt;Define functions you want to make use of and how their arguments and return values map to your host language data types&lt;/li&gt;
&lt;li&gt;(Optionally) Define the calling convention&lt;/li&gt;
&lt;li&gt;Use those functions as if they were native to your host language&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s see how it looks in Ruby. The first step is to define a module you want to “attach” external functions to. This very often looks similar to the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;module&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;SomeLibrary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080&#34;&gt;extend&lt;/span&gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;FFI&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Library&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;# (...)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;FFI::Library&lt;/code&gt; module brings in useful methods for defining the linkage with the target, external library. We still need to “tell” Ruby the external library we want to work with. Here’s an example of working with &lt;code&gt;fribidi&lt;/code&gt;, which contains lots of very useful functions for working with bidirectional Unicode text:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;module&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Bidi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080&#34;&gt;extend&lt;/span&gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;FFI&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Library&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ffi_lib [&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;libfribidi&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888&#34;&gt;# (...)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let’s say that we want to use a very helpful &lt;code&gt;fribidi_log2vis&lt;/code&gt; function. We’ll want it to give us a logical position index for each visual position index of the text, given a directionality of it.&lt;/p&gt;
&lt;p&gt;Disclaimer:
If the language you speak uses Latin-based script in writing, you might be scratching your head now. For most languages the logical positions of characters are the same as the “visual” ones (where those characters end up visually in the word / token). This is not always the case. Counterexamples include Arabic, Hebrew, and Syriac (among others). A line of text could also contain words / tokens written using different scripts (like e.g. names of places written in the Latin script, inside a RTL paragraph). Sometimes also e.g. the punctuation might appear in one place logically in the string, while visually somewhere else.&lt;/p&gt;
&lt;p&gt;The signature of the function reads as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fribidi_boolean &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;fribidi_log2vis&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;/* input */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FriBidiChar     *str,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FriBidiStrIndex len,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FriBidiCharType *pbase_dir,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888&#34;&gt;/* output */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FriBidiChar     *visual_str,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FriBidiStrIndex *position_L_to_V_list,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FriBidiStrIndex *position_V_to_L_list,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    FriBidiLevel    *embedding_level_list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In order to use this function from Ruby, we need to tell it what those types mean in terms of types available in Ruby and the &lt;code&gt;ffi&lt;/code&gt; gem:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;module&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Bidi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080&#34;&gt;extend&lt;/span&gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;FFI&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Library&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ffi_lib [&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;libfribidi&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  attach_function &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:fribidi_log2vis&lt;/span&gt;, [ &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:pointer&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:int32&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:pointer&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:pointer&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:pointer&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:pointer&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:pointer&lt;/span&gt; ], &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:bool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The full documentation on the types mappings can be &lt;a href=&#34;https://github.com/ffi/ffi/wiki/Types&#34;&gt;found here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We’re now ready to wrap our newly attached external function inside a convenient Ruby code. We’ll create a &lt;code&gt;to_visual_indices&lt;/code&gt; method on the &lt;code&gt;Bidi&lt;/code&gt; module that will take a string and a symbol representing the directionality. The directionality will expect &lt;code&gt;:rtl&lt;/code&gt; for the RTL direction. Here’s the listing of how it looks:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;module&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;Bidi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080&#34;&gt;extend&lt;/span&gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;FFI&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Library&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ffi_lib [&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;libfribidi&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  attach_function &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:fribidi_log2vis&lt;/span&gt;, [ &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:pointer&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:int32&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:pointer&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:pointer&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:pointer&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:pointer&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:pointer&lt;/span&gt; ], &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:bool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;to_visual_indices&lt;/span&gt;(text, direction)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    null = &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;FFI&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Pointer&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;NULL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    t = &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;FFI&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;MemoryPointer&lt;/span&gt;.new(&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:uint32&lt;/span&gt;, text.codepoints.count)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    t.put_array_of_uint32(&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;, text.codepoints)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    pos = &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;FFI&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;MemoryPointer&lt;/span&gt;.new(&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:int&lt;/span&gt;, text.codepoints.count)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dir_spec = &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;FFI&lt;/span&gt;::&lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;MemoryPointer&lt;/span&gt;.new(&lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:long&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dir_spec.write_long( direction == &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:rtl&lt;/span&gt; ? &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;273&lt;/span&gt; : &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;272&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    success = &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Lib&lt;/span&gt;.fribidi_log2vis(t, text.codepoints.count, dir_spec, null, null, pos, null)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; success
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;return&lt;/span&gt; pos.read_array_of_int(text.codepoints.count)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;raise&lt;/span&gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;StandardError&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Failed to infer the visual ordering of the text&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You could now use your new module along with the new method that uses an external library:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;span style=&#34;color:#036;font-weight:bold&#34;&gt;Bidi&lt;/span&gt;.to_visual_indices &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Friendship الصداقة&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a60;background-color:#fff0f0&#34;&gt;:rtl&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;=&amp;gt; [&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;17&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;16&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;15&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;14&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;13&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;12&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;11&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;5&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;6&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;7&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;8&lt;/span&gt;, &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;9&lt;/span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using &lt;code&gt;FFI&lt;/code&gt; in Ruby is a great way to bring in existing external functionality without the need to write an extension in C. It also spares you from the need to compile it, which in the case of Rails is very, very convenient.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>A Collaborative Timezone Utility</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2017/10/a-collaborative-timezone-utility/"/>
      <id>https://www.endpointdev.com/blog/2017/10/a-collaborative-timezone-utility/</id>
      <published>2017-10-30T00:00:00+00:00</published>
      <author>
        <name>Joe Marrero</name>
      </author>
      <content type="html">
        &lt;div style=&#34;float: right; width: 300px; padding: 0 0 1em 1em;&#34;&gt;
  &lt;div style=&#34;padding: 1em; border: 1px solid #ccc; border-radius: 6px;&#34;&gt;
    &lt;h3 style=&#34;margin: 0 0 1rem 0;&#34;&gt;Try It Out Yourself&lt;/h3&gt;
    &lt;p&gt;The code for this project is hosted on &lt;a href=&#34;https://github.com/manvscode/timezoner&#34;&gt;GitHub and can be cloned from here.&lt;/a&gt;&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;At &lt;a href=&#34;/&#34;&gt;End Point Corporation&lt;/a&gt;, our team is spread out across 10 time zones. This gives us the advantage of being able to work around the clock on projects. When one co-worker leaves for day, another can take over. Consider this scenario. It&amp;rsquo;s Monday evening and Martin needs to continue installing software on that Linux cluster, but it&amp;rsquo;s already 6pm and his wife is going to murder him if he&amp;rsquo;s not ready to go out for their anniversary dinner. Let&amp;rsquo;s see who can take over&amp;hellip; Ah, yes, Sanjay in Bangalore can continue with the maintenance. Tuesday morning, the client wakes up to be surprised that 16 hours of work was completed in a day. With respect to software development, the same efficiencies can be realized by parallelizing tasks across time-zones. Code reviews and further development can be continued after normal business hours.&lt;/p&gt;
&lt;p&gt;With all the blessings of a distributed engineering team, collaborating with co-workers can be, occasionally, challenging. Some of these challenges stem from complexities of our system of time. Every co-worker may be operating in a timezone that is different than yours. Time-zones have an associated offset relative to &lt;a href=&#34;https://en.wikipedia.org/wiki/Coordinated_Universal_Time&#34;&gt;Coordinated Universal Time (UTC)&lt;/a&gt;. These offsets are usually in whole hour increments but they may be any real-valued number.&lt;/p&gt;
&lt;p&gt;For example, &lt;a href=&#34;https://en.wikipedia.org/wiki/Eastern_Time_Zone&#34;&gt;Eastern Standard Time (EST)&lt;/a&gt; has an offset of -5 (five hours behind UTC) and &lt;a href=&#34;https://en.wikipedia.org/wiki/Indian_Standard_Time&#34;&gt;Indian Standard Time (IST)&lt;/a&gt; has an offset of 5.5 (five and half hours ahead of UTC). Furthermore, these UTC offsets can be completely arbitrary. In 1995, &lt;a href=&#34;https://en.wikipedia.org/wiki/Kiribati&#34;&gt;Kiribati&lt;/a&gt;, an island nation in the Pacific, changed its UTC offset from -10 to +14 so that all of its outlying islands can share the same time. To further complicate things, some regions may not observe &lt;a href=&#34;https://en.wikipedia.org/wiki/Daylight_saving_time&#34;&gt;daylight savings time (DST)&lt;/a&gt; while other regions do. In fact, in the United States, Indiana started observing DST on April 2, 2006. Some states like Arizona and Hawaii do not observe DST. Other countries, like Australia, have a similar situation where it&amp;rsquo;s left to local governments to decide whether DST is observed or not. Moreover, although DST usually accounts for adding or subtracting an hour of time, it isn&amp;rsquo;t always one hour. This has historically changed from time to time.&lt;/p&gt;
&lt;p&gt;Now you may begin to imagine the headaches that arise when you need to coordinate with anything involving multiple time-zones. To make all of this easier, you can use a utility that we wrote to do all the time conversions for you. First, you have to add each co-worker&amp;rsquo;s information to a configuration file stored at ~/.timezoner. This configuration file will describe all of your co-worker&amp;rsquo;s contact information and their associated IANA time-zone. As an example, this is what the configuration file looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# Timezone            Email                  Name              OfficePhone        MobilePhone&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;America/New_York      &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;edward@example.com&amp;#34;&lt;/span&gt;   &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Edward Teach &amp;#34;&lt;/span&gt;   &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;n/a&amp;#34;&lt;/span&gt;              &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;+1 731 555 1234&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;America/New_York      &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;henry@dexample.com&amp;#34;&lt;/span&gt;   &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Henry Morgan&amp;#34;&lt;/span&gt;    &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;+1 646 555 5678&amp;#34;&lt;/span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;+1 954 555 5678&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;America/New_York      &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;john@example.com&amp;#34;&lt;/span&gt;     &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;John Auger&amp;#34;&lt;/span&gt;      &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;n/a&amp;#34;&lt;/span&gt;              &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;+1 902 555 1234&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;America/Denver        &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;sam@example.com&amp;#34;&lt;/span&gt;      &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Samuel Bellamy&amp;#34;&lt;/span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;+1 347 535 1234&amp;#34;&lt;/span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;+1 994 555 5678&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;America/Los_Angeles   &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;william@example.com&amp;#34;&lt;/span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;William Kidd&amp;#34;&lt;/span&gt;    &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;+1 330 555 5678&amp;#34;&lt;/span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;+1 305 555 1234&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;America/Los_Angeles   &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;israel@example.com&amp;#34;&lt;/span&gt;   &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;Israel Hands&amp;#34;&lt;/span&gt;    &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;+1 507 555 1234&amp;#34;&lt;/span&gt;  &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;+1 208 555 5678&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now when I need to coordinate a meeting, I can run the utility with the -T option to see each team member&amp;rsquo;s local time.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center; margin-bottom: 1em;&#34;&gt;&lt;a href=&#34;/blog/2017/10/a-collaborative-timezone-utility/image-0-big.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; data-original-height=&#34;320&#34; data-original-width=&#34;1600&#34; height=&#34;172&#34; src=&#34;/blog/2017/10/a-collaborative-timezone-utility/image-0.png&#34; width=&#34;846&#34; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;With the -U option, you can display each contact separated in groups based on UTC offset.&lt;/p&gt;
&lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center; margin-bottom: 1em;&#34;&gt;&lt;a href=&#34;/blog/2017/10/a-collaborative-timezone-utility/image-1-big.png&#34; imageanchor=&#34;1&#34; style=&#34;margin-left: 1em; margin-right: 1em;&#34;&gt;&lt;img border=&#34;0&#34; data-original-height=&#34;833&#34; data-original-width=&#34;1600&#34; height=&#34;333&#34; src=&#34;/blog/2017/10/a-collaborative-timezone-utility/image-1.png&#34; width=&#34;640&#34; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;Let us know what you think and if you found this tool helpful.&lt;/p&gt;

      </content>
    </entry>
  
</feed>
