Dart FFI and Linux
Tags: programming, computerscience, flutter, productivity
Published: 2021-06-18 04:18:46

*In case it helped :)*
<a href="https://www.buymeacoffee.com/aseemwangoo" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Pass Me A Coffee!!" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>

<!-- wp:paragraph -->
<p>We will cover briefly about</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>Creating C Library</li><li>Call from Flutter on Linux</li><li>Passing parameter from Dart to C</li><li>Passing structs from Dart to C</li></ol>
<!-- /wp:list -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Note: We won’t be explaining in-depth about Dart FFI as there are good articles dedicated to it.&nbsp;</p></blockquote>
<!-- /wp:quote -->

{% youtube Hd-tJT-csdM %}

<!-- wp:heading {"level":3} -->
<h3>Creating C Library on&nbsp;Linux</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>We are going to create the following use cases</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li><strong>Generate random number from C</strong></li></ol>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Let’s create a c file named <strong>random_number.c </strong>For generating random number in c, we use <a href="https://linuxhint.com/rand-function-in-c-language/" rel="noreferrer noopener" target="_blank">rand</a>. Here is the snippet</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>int fetch_number()
{
    int c, n;
    srand(time(0));
    n = rand() % 100 + 1;
    return n;
}</code></pre>
<!-- /wp:code -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Note: We are capping the values from 0 to 100</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>We will create a header file <strong>randomnumber.h, </strong>and paste the declaration of our function inside it.</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>// randomnumber.h
int fetch_number();</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Inside our random_number.c, we will import this header file and implement the definition of <code>fetch_number</code> . Our final file looks like this</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>#include &lt;stdio.h>
#include &lt;stdlib.h>
#include &lt;time.h>
#include "randomnumber.h"
int main()
{
    return 0;
}
// Definition omitted for brevity. Basically, it's the above function only :)</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Let’s test our c function, navigate to the folder containing the program and run</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>gcc random_number.c -o random_number</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>This generates our output file as <strong>random_number.o </strong>Run this output file by</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>./random_number</code></pre>
<!-- /wp:code -->

<!-- wp:image {"align":"center"} -->
<div class="wp-block-image"><figure class="aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/1*m8oK4HIhaSpnaz1h1aaI0A.png" alt="Output from C library"/><figcaption>Output from C library</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:list -->
<ul><li>Next, we will create our dynamic library (<strong>librandomnumber.so</strong>)</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>To create a dynamic library, write the following command:</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>gcc -shared -o librandomnumber.so random_number.o
// librandomnumber.o is the name of your dynamic library
// random_number.o is the object file created from the above step</code></pre>
<!-- /wp:code -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Note: The library name can be anything, but should start with <code>“lib”</code> and end with <code>&nbsp;<strong>.so</strong></code></p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>The <code>compiler</code> will later identify a library by searching for files beginning with <code>“lib”</code> and ending with the naming convention,<code> <strong>.so</strong></code></p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center"} -->
<div class="wp-block-image"><figure class="aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/1*ybAI7ui0za-_Y6-61bp5MA.png" alt="Dynamic Library in Linux"/><figcaption>Dynamic Library in&nbsp;Linux</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:heading {"level":3} -->
<h3>Call from Flutter on&nbsp;Linux</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Drag and drop the library <strong>(librandomnumber.so) </strong>in our flutter project. We create a library subfolder and drop it there.</p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center"} -->
<div class="wp-block-image"><figure class="aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/1*kPE49BNrdwC4xLhdr0Zoag.png" alt="Libraries inside Flutter project"/><figcaption>Libraries inside Flutter project</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:image {"align":"center"} -->
<div class="wp-block-image"><figure class="aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/1*H3duHZD0ueog7oFfZNZupg.png" alt="Steps to call a function from C"/><figcaption>Steps to call a function from&nbsp;C</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>We will call our dynamic libraries from Flutter Desktop now using Dart FFI in Linux</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Import the dart ffi package(present inside Flutter) as</li></ul>
<!-- /wp:list -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">import 'dart:ffi'</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>This has a class <strong>DynamicLibrary. </strong>We call the method <strong>open </strong>and load our dynamic library (librandomnumber.so).</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">final dyLib = DynamicLibrary.open(<br>   'lib/library/linux/librandomnumber.so',<br>);</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>Lookup for the symbol from the loaded dynamic library using <strong>lookup</strong> or <strong>lookupFunction.</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>dyLib.lookup&lt;NativeFunction&lt;fetch_number_func>>(
   'fetch_number',
);
// This returns a pointer</code></pre>
<!-- /wp:code -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Note: The lookup takes in a native function (which represents a function in C)</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>Our fetch_number_func is basically</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">typedef fetch_number_func = Int32 Function();</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>and this Int32 comes from dart:ffi, which represents a native signed 32 bit integer in C.</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>The pointer returned from the above step is converted into Dart function</li></ul>
<!-- /wp:list -->

<!-- wp:code -->
<pre class="wp-block-code"><code>final number = fetchNumberPointer.asFunction&lt;FetchNumber>();
number(); // Call the function</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>where FetchNumber is our function</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">typedef FetchNumber = int Function();</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p><strong>Passing parameter from Dart to C</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Let’s create a c file named <strong>string_ops.c </strong>We will define a function, which takes in a string parameter, reverses it, and sends it back. Here is the snippet</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>void reverse(char *str) {
  // Calculate length of string.
  int l = 0;
  while (*(str + l) != '\0')
    l++;
// Initialize.
  int i;
  char *first, *last, temp;
  first = str;
  last = str;
  for (i = 0; i &lt; l - 1; i++) {
    last++;
  }
// Iterate from both ends, swapping first and last as we go.
  for (i = 0; i &lt; l / 2; i++) {
    temp = *last;
    *last = *first;
    *first = temp;
first++;
    last--;
  }
}</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>As seen in the above section, we will create a header file <strong>stringops.h </strong>and paste the declaration of our function inside it.</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>// stringops.h
void reverse(char *str);</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Inside our <strong>string_ops</strong>.c, we will import this header file and implement the definition of <code>reverse</code> . Our final file looks like this</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>#include&lt;stdio.h>
#include "stringops.h"
int main()
{
 return 0;
}
// Definition omitted for brevity. Basically, it's the above function only :)</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Finally, we create our header file, <strong>libstringops.so (see the steps above)</strong></p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>Call from&nbsp;Flutter</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>We copy-paste this header file inside our flutter project</p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center"} -->
<div class="wp-block-image"><figure class="aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/1*kPE49BNrdwC4xLhdr0Zoag.png" alt="Libraries inside Flutter project"/><figcaption>Libraries inside Flutter project</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>Open the dynamic library using the dart ffi</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>final dylib = DynamicLibrary.open(
   'lib/library/linux/libstringops.so',
);</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Now we need to pass in the parameter, and this should be something that C understands. In short, we need to convert our <strong>Flutter Strings</strong> to <strong>Pointer.</strong></p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Time to include package <a href="https://pub.dev/packages/ffi" rel="noreferrer noopener" target="_blank"><em>FFI</em></a></p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>Our input (let's say a string) can be converted to <a href="https://pub.dev/documentation/ffi/latest/ffi/Utf8-class.html" rel="noreferrer noopener" target="_blank">UTF-8 pointer</a> using <a href="https://pub.dev/documentation/ffi/latest/ffi/StringUtf8Pointer/toNativeUtf8.html" rel="noreferrer noopener" target="_blank"><strong>toNativeUTF8</strong></a>,</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>String input = 'hello world';
final inputToUtf8 = input.toNativeUtf8();</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Next, we need to look up the function</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>final reverse = dylib.lookupFunction&lt;Void Function(Pointer&lt;Utf8>),
        void Function(Pointer&lt;Utf8>)>('reverse');</code></pre>
<!-- /wp:code -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Note: First param is the C function signature, and second param is the Dart function signature.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>Now, we have a function that takes in a parameter of <code>Pointer&lt;Utf8></code> and we pass in our <code>inputToUtf8</code> </p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>reverse(inputToUtf8);
final resp = inputToUtf8.toDartString();</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Finally, the response(which is of type UTF-8) is converted <a href="https://pub.dev/documentation/ffi/latest/ffi/Utf8Pointer/toDartString.html" rel="noreferrer noopener" target="_blank"><strong>toDartString</strong></a></p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>One last thing, <a href="https://pub.dev/documentation/ffi/latest/ffi/StringUtf8Pointer/toNativeUtf8.html" rel="noreferrer noopener" target="_blank">toNativeUtf8</a> uses an allocator to allocate C memory. Remember, in C we need to explicitly free the memory used.</li><li>This is done by calling <a href="https://pub.dev/documentation/ffi/latest/ffi/Arena/free.html" rel="noreferrer noopener" target="_blank">free</a> </li></ul>
<!-- /wp:list -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">malloc.free(inputToUtf8);</pre>
<!-- /wp:preformatted -->

<!-- wp:heading {"level":3} -->
<h3>Passing structs from Dart to&nbsp;C</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>In the header file <strong>stringops.h, </strong>let’s add in our <a href="https://www.programiz.com/c-programming/c-structures-pointers" rel="noreferrer noopener" target="_blank">struct</a></p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>struct Name
{
    char *firstname;
    char *lastname;
};
struct Name create_name(char *firstname, char *lastname);</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Inside our <strong>string_ops</strong>.c, we have already imported this header file. Let’s implement the definition of <code>create_name</code> . Our final file looks like this</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>#include&lt;stdio.h>
#include "stringops.h"
int main()
{
 return 0;
}
struct Name create_name(char *firstname, char *lastname) {
 struct Name name;
 name.firstname = firstname;
 name.lastname = lastname;
 return name; 
}</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Finally, we create our header file, <strong>libstringops.so (see the steps above)</strong></p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>Call from&nbsp;Flutter</h4>
<!-- /wp:heading -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Note: We require <a href="https://medium.com/dartlang/announcing-dart-2-12-499a6e689c87" target="_blank" rel="noreferrer noopener">Dart 2.12</a> and onwards to call structs from ffi</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>We copy-paste this header file inside our flutter project</p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center"} -->
<div class="wp-block-image"><figure class="aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/1*kPE49BNrdwC4xLhdr0Zoag.png" alt="Libraries inside Flutter project"/><figcaption>Libraries inside Flutter&nbsp;project</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>We already have our dynamic library opened (see the above section), now we need to look up our <code>create_name</code> function.</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>final createName =
  dylib.lookupFunction&lt;CreateNameNative, CreateName>('create_name');</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>As we know now, the lookup function takes in a C function and a Dart function. Our functions look like</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>// For structs
typedef CreateNameNative = Name Function(
    Pointer&lt;Utf8> firstName, Pointer&lt;Utf8> lastName);
typedef CreateName = Name Function(
    Pointer&lt;Utf8> firstName, Pointer&lt;Utf8> lastName);</code></pre>
<!-- /wp:code -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>since, we need to pass in the two parameters</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>Now, here is something new, we have <code>Name</code> </p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>class Name extends Struct {
  external Pointer&lt;Utf8> firstName;
  external Pointer&lt;Utf8> lastName;
}</code></pre>
<!-- /wp:code -->

<!-- wp:list -->
<ul><li>Dart introduces <a href="https://api.dart.dev/stable/2.12.1/dart-ffi/Struct-class.html" rel="noreferrer noopener" target="_blank">Struct</a>, the supertype of all FFI struct types.</li><li>FFI struct types should extend this class and declare fields corresponding to the underlying native structure.</li><li>All field declarations in a <a href="https://api.dart.dev/stable/2.12.1/dart-ffi/Struct-class.html" rel="noreferrer noopener" target="_blank">Struct</a> subclass declaration must be marked <code>external</code></li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Rest is the same, we pass in our inputs as toNativeUtf8</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>String first = 'Aseem';
String second = 'Wangoo';
final fNameUtf8 = first.toNativeUtf8();
final lNameUtf8 = second.toNativeUtf8();
final name = createName(fNameUtf8, lNameUtf8);
// createName is from the above</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Finally, we have our response in the variable <code>name</code> The response(which is of type UTF-8) is converted <a href="https://pub.dev/documentation/ffi/latest/ffi/Utf8Pointer/toDartString.html" rel="noreferrer noopener" target="_blank"><strong>toDartString</strong></a></p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>final fname = name.firstName.toDartString();
final lname = name.lastName.toDartString();</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>The memory is freed using <a href="https://pub.dev/documentation/ffi/latest/ffi/Arena/free.html" rel="noreferrer noopener" target="_blank">free</a></p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>malloc.free(fNameUtf8);
malloc.free(lNameUtf8);</code></pre>
<!-- /wp:code -->

{% youtube Hd-tJT-csdM %}

<!-- wp:paragraph -->
<a href="https://github.com/AseemWangoo/flutter_programs/blob/master/ffi_linux.zip" rel="noreferrer noopener" target="_blank">Source Code</a>
<!-- /wp:paragraph -->

*In case it helped :)*
<a href="https://www.buymeacoffee.com/aseemwangoo" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Pass Me A Coffee!!" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>