FlutterDesktop and C
Tags: computerscience, flutter, productivity, programming
Published: 2020-12-26 06:15:52

*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><strong><em>Website: </em></strong><a href="https://web.flatteredwithflutter.com/#/" rel="noreferrer noopener" target="_blank"><strong><em>https://web.flatteredwithflutter.com/#/</em></strong></a></p>
<!-- /wp:paragraph -->

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

<!-- wp:paragraph -->
<p>This article assumes that the reader has knowledge about FFI. In case not, check <a href="https://medium.com/p/8cc5ed2f8aae/edit" target="_blank" rel="noreferrer noopener">this</a>.</p>
<!-- /wp:paragraph -->

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

<!-- wp:list {"ordered":true} -->
<ol><li>Creating C Library</li><li>Integrate C Library in Flutter MacOS</li><li>Call from Flutter MacOS</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.</p></blockquote>
<!-- /wp:quote -->

{% youtube LUQBDT02ha0 %}

####Article here: https://flatteredwithflutter.com/flutterdesktop-and-c/

<!-- wp:heading {"level":4} -->
<h4>Creating C&nbsp;Library</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Every complicated thing starts with a basic thing. Let’s create a simple C library <strong>(Hello World)</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><strong>Introducing </strong><a href="https://cmake.org/" rel="noreferrer noopener" target="_blank"><strong>CMake</strong></a><strong> and makefile</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Creating a c library involves a bunch of commands, either you can use those or you can utilize CMake.</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*ZUncgIyrVGJ8mrXBKKC64Q.png" alt="FlutterDesktop and C | CMake"/><figcaption>FlutterDesktop and C |&nbsp;CMake</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>As per the documentation</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p><strong>CMake</strong> is an extensible, open-source system that manages the build process in an operating system and in a compiler-independent manner.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>Install CMake using</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><code>brew install cmake</code></p>
<!-- /wp:paragraph -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:paragraph -->
<p>CMake uses a text file named <strong>CMakeLists.txt</strong>, in the home directory of the software package, to specify the actions that are necessary to set up the software. The user begins the build process by moving to the home directory and typing</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">cmake .</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>CMake will carry out a configuration process, after which a traditional Makefile will be created in the home directory. The software process is then completed by typing</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">make</pre>
<!-- /wp:preformatted -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:paragraph -->
<p>Create a C header file, <strong>hello.h</strong>, which has 1 function declaration</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">void hello_world();</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>Let’s import this header file in our <strong>hello.c</strong></p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">#include &lt;stdio.h&gt;
#include "hello.h"  // OUR HEADER FILE

int main()
{
    hello_world();  // FUNCTION FROM HEADER FILE
    return 0;
}

void hello_world()  // IMPLEMENTATION OF FUNCTION
{
    printf("Hello World\n");
}</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>Our folder structure looks like this</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*wS6QPmspeEAMWlpN3AzI-A.png" alt="FlutterDesktop and C | Folder Structure | Before"/><figcaption>FlutterDesktop and C | Folder Structure |&nbsp;Before</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>Finally, inside our CMakeLists.txt we define the commands as</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">cmake_minimum_required(VERSION 3.10)
project(first_c VERSION 1.0 LANGUAGES C)
add_library(first_c SHARED hello.c)
add_executable(hello_test hello.c)

set_target_properties(first_c PROPERTIES
    PUBLIC_HEADER hello.h
    VERSION ${PROJECT_VERSION}
    SOVERSION 1
    OUTPUT_NAME "hello"
)</pre>
<!-- /wp:preformatted -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted"></pre>
<!-- /wp:preformatted -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Note: <a href="https://cmake.org/cmake/help/v3.0/manual/cmake-commands.7.html" rel="noreferrer noopener" target="_blank">CMake commands list</a></p></blockquote>
<!-- /wp:quote -->

<!-- wp:list -->
<ul><li><strong>cmake_minimum_required</strong>: Set the minimum required version of CMake for a project.</li><li><strong>project</strong>: Set a name, version, and enable languages for the entire project.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Here, we are using <strong>first_c (our parent folder name)</strong>, version 1.0, and language as C.</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li><strong>add_library</strong>: Add a library to the project using the specified source files.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Our project is <strong>first_c</strong> and we specify <strong>Shared (Dynamic Library) </strong>to be created out of our <strong>hello.c</strong> program</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li><strong>add_executable</strong>: Add an executable to the project using the specified source files.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>This creates an executable(<strong>hello_test</strong>) from our source (<strong>hello.c</strong>), which we can test for our generated shared library.</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li><strong>set_target_properties: </strong>Targets can have properties that affect how they are built.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Here, our project is <strong>first_c</strong>, and properties are written as&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">PROPERTIES prop1 value1</pre>
<!-- /wp:preformatted -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:paragraph -->
<p>Now run the commands&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">cmake .
make</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>You will see our folder structure now as:</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*3g5Xy_8hEJs-BFYWZG_SnA.png" alt="FlutterDesktop and C | Folder Structure | After"/><figcaption>FlutterDesktop and C | Folder Structure |&nbsp;After</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Hurray, we have our <strong>libhello.dylib </strong>now!!</p></blockquote>
<!-- /wp:quote -->

<!-- wp:heading {"level":4} -->
<h4>Integrate C Library in Flutter&nbsp;MacOS</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Now we need to integrate the C library in our Flutter Desktop application.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The steps needed are documented in <a href="https://flutter.dev/docs/development/platform-integration/c-interop#compiled-dynamic-library-macos" rel="noreferrer noopener" target="_blank">this link</a>, follow along with the article or the above video.</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>Open the <code>yourapp/macos/Runner.xcworkspace</code> in Xcode</li><li>Drag your precompiled library (<code>libyourlibrary.dylib</code>) into <code>Runner/Frameworks</code>.</li><li>Click <code>Runner</code> and go to the <code>Build Phases</code> tab.</li></ol>
<!-- /wp:list -->

<!-- wp:list -->
<ul><li>Drag <code>libyourlibrary.dylib</code> into the <code>Copy Bundle Resources</code> list.</li><li>Under <code>Bundle Framework</code>, check <code>Code Sign on Copy</code>.</li><li>Under, <code>Link Binary With Libraries</code> set status to <code>Optional</code>.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>4. Click <code>Runner</code> and go to the <code>General</code> tab.</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Drag <code>libyourlibrary.dylib</code> into the <code>Frameworks, Libararies and Embedded Content</code> list.</li><li>Select <code>Embed &amp; Sign</code>.</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Your Flutter Desktop project structure should look like this</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*kKDJvseKk3GNLeNzyKlXYw.png" alt="FlutterDesktop and C | Folder Structure | Flutter"/><figcaption>FlutterDesktop and C | Folder Structure | Flutter</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

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

<!-- wp:paragraph -->
<p>We will call our dynamic libraries from Flutter Desktop now.</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' as 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 (libhello.dylib).</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Lookup for the symbol from the loaded dynamic library using <strong>lookup</strong> or <strong>lookupFunction.</strong></li><li>Finally, call the function ‘<strong>hello_world</strong>’ (exposed from header file&nbsp;.h)</li></ul>
<!-- /wp:list -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">typedef hello_world_func = ffi.Void Function();

void openFromFlutter() {
  final sysLib = ffi.DynamicLibrary.open('libhello.dylib');

  final HelloWorld hello = sysLib
      .lookup&lt;ffi.NativeFunction&lt;hello_world_func&gt;&gt;('hello_world')
      .asFunction();
    
  hello(); // Call the function
}</pre>
<!-- /wp:preformatted -->

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

<!-- wp:paragraph -->
<p>Let’s say we have a function in the C header file like this</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">char *sayHello(char *str);</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>Since this accepts the input parameter and the return type as <strong>char pointer</strong>, we need to convert our <strong>Flutter Strings</strong> to/from <strong>Pointer.</strong></p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>We specify <strong>SystemCHello</strong> and <strong>SystemDartHello</strong> functions, which basically are</li></ul>
<!-- /wp:list -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">typedef SystemCHello = ffi.Pointer&lt;Utf8&gt; Function(ffi.Pointer&lt;Utf8&gt; str);

typedef SystemDartHello = ffi.Pointer&lt;Utf8&gt;Function(ffi.Pointer&lt;Utf8&gt; str);</pre>
<!-- /wp:preformatted -->

<!-- wp:list -->
<ul><li>Convert our Flutter String to Utf8 and pass it to the function</li></ul>
<!-- /wp:list -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">final sysLib = ffi.DynamicLibrary.open('libfetchtemp.dylib');

final helloFromC = sysLib.lookupFunction&lt;SystemCHello, SystemDartHello&gt;('sayHello');

// Pass input
final name = Utf8.toUtf8(input);

// Call the function
final res = helloFromC(name);</pre>
<!-- /wp:preformatted -->

<!-- wp:list -->
<ul><li>Since the value returned from the function, is also a pointer, we convert it to Flutter String</li></ul>
<!-- /wp:list -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">// Convert response into string<br>final strRes = Utf8.fromUtf8(res);</pre>
<!-- /wp:preformatted -->

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

{% youtube LUQBDT02ha0 %}

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p><a href="https://github.com/AseemWangoo/Experiments_with_Desktop" rel="noreferrer noopener" target="_blank">Source code for Flutter Desktop App..</a></p></blockquote>
<!-- /wp:quote -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Hosted URL&nbsp;: <a href="https://web.flatteredwithflutter.com/#/" rel="noreferrer noopener" target="_blank">https://web.flatteredwithflutter.com/#/</a></p></blockquote>
<!-- /wp:quote -->