Flutter FFI Example

1,531 views
Skip to first unread message

Craig Jarman

unread,
Sep 11, 2019, 11:59:46 PM9/11/19
to Dart FFI
I'd be interested to know if there is an example of how to use a simple C-library in Flutter, such as may be found in the primitives c-library example.

I'm getting an error on linking to the compiled dynamic link library:

This line of code:

final dylib = ffi.DynamicLibrary.open('primitives.dylib');

Throws this error:
 
"Invalid argument(s): Failed to load dynamic library (dlopen(primitives.dylib, 1): image not found)"

The 'primitives.dylib' I have placed in the lib directory.

Thanks


 

Message has been deleted

Craig Jarman

unread,
Sep 12, 2019, 1:10:35 AM9/12/19
to Dart FFI
Also including the files is XCode result in a platform mismatch.

 

d: warning: ignoring file /Users/xxx/flutterApps/ffitest/ios/Runner/primitives.dylib, file was built for x86_64 which is not the architecture being linked (arm64): /Users/xxx/flutterApps/ffitest/ios/Runner/primitives.dylib

Daco Harkes

unread,
Sep 12, 2019, 5:14:04 AM9/12/19
to Craig Jarman, Dart FFI
Hey Craig,

You should use the dylib that is compiled for arm64 instead of intel64.

See https://github.com/flutter/flutter/wiki/Binding-to-native-code-via-FFI for more information on how to bind to native code in iOS.

Kind regards,

On Thu, Sep 12, 2019 at 7:10 AM Craig Jarman <craig.m...@gmail.com> wrote:
Also including the files is XCode result in a platform mismatch.

 

d: warning: ignoring file /Users/xxx/flutterApps/ffitest/ios/Runner/primitives.dylib, file was built for x86_64 which is not the architecture being linked (arm64): /Users/xxx/flutterApps/ffitest/ios/Runner/primitives.dylib

--
You received this message because you are subscribed to the Google Groups "Dart FFI" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dart-ffi+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dart-ffi/d806c536-fdcc-4712-8792-a27459f0f6ce%40googlegroups.com.


--
Daco Harkes

Craig Jarman

unread,
Sep 12, 2019, 5:22:39 AM9/12/19
to Dart FFI
Hi Daco

I have read this page.

My understanding is the is that the dylib is compiled using the makefile. 

Is there a way to instruct the instruct the file to compile for arm64, rather than assume intel64?

Thanks




primitives: primitives.o
 gcc
-o a.out primitives.o


primitives
.o: primitives.c
 gcc
-c primitives.c


dylib
: primitives.o
 gcc
-dynamiclib -undefined suppress -flat_namespace primitives.o -o ../primitives.dylib


clean
:
 rm a
.out primitives.o ../primitives.dylib





On Thursday, 12 September 2019 19:14:04 UTC+10, Daco Harkes wrote:
Hey Craig,

You should use the dylib that is compiled for arm64 instead of intel64.

See https://github.com/flutter/flutter/wiki/Binding-to-native-code-via-FFI for more information on how to bind to native code in iOS.

Kind regards,

On Thu, Sep 12, 2019 at 7:10 AM Craig Jarman <craig....@gmail.com> wrote:
Also including the files is XCode result in a platform mismatch.

 

d: warning: ignoring file /Users/xxx/flutterApps/ffitest/ios/Runner/primitives.dylib, file was built for x86_64 which is not the architecture being linked (arm64): /Users/xxx/flutterApps/ffitest/ios/Runner/primitives.dylib

--
You received this message because you are subscribed to the Google Groups "Dart FFI" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dart...@googlegroups.com.


--
Daco Harkes

Daco Harkes

unread,
Sep 12, 2019, 5:24:36 AM9/12/19
to Craig Jarman, Dart FFI
Hey Craig,

You need to use a cross-compiler from intel to arm.


Kind regards,

To unsubscribe from this group and stop receiving emails from it, send an email to dart-ffi+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dart-ffi/5dee3277-cd31-43e2-a5f8-9502448d4a93%40googlegroups.com.


--
Daco Harkes

Samir Jindel

unread,
Sep 12, 2019, 5:35:44 AM9/12/19
to Daco Harkes, Craig Jarman, Dart FFI
Are you trying to create a Flutter plugin? If so, it would be easier to create a Cocoa Pod, which will handle compiling a "fat" library (containing all architectures) and linking it correctly.
The wiki page (https://github.com/flutter/flutter/wiki/Binding-to-native-code-via-FFI) does not recommend using a Makefile on OSX.

Craig Jarman

unread,
Sep 12, 2019, 5:39:44 AM9/12/19
to Dart FFI
No, wasn't thinking to create a flutter plugin. Not at this stage anyway.

On Thursday, 12 September 2019 19:35:44 UTC+10, Samir Jindel wrote:
Are you trying to create a Flutter plugin? If so, it would be easier to create a Cocoa Pod, which will handle compiling a "fat" library (containing all architectures) and linking it correctly.
The wiki page (https://github.com/flutter/flutter/wiki/Binding-to-native-code-via-FFI) does not recommend using a Makefile on OSX.

On Thu, Sep 12, 2019 at 11:24 AM 'Daco Harkes' via Dart FFI <dart...@googlegroups.com> wrote:
Hey Craig,

You need to use a cross-compiler from intel to arm.


Kind regards,



--
Daco Harkes

--
You received this message because you are subscribed to the Google Groups "Dart FFI" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dart...@googlegroups.com.

Samir Jindel

unread,
Sep 12, 2019, 5:41:20 AM9/12/19
to Craig Jarman, Dart FFI
Can you just include your sources in the Xcode app directly then?

To unsubscribe from this group and stop receiving emails from it, send an email to dart-ffi+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dart-ffi/4e0b8a8d-3419-4e20-ae82-2a6e8a2f2746%40googlegroups.com.

Craig Jarman

unread,
Sep 12, 2019, 5:54:05 AM9/12/19
to Dart FFI
That would be ideal, but there are no examples for using C code directly.

FFI asks for a DynamicLibrary however.



On Thursday, 12 September 2019 19:41:20 UTC+10, Samir Jindel wrote:
Can you just include your sources in the Xcode app directly then?

Craig Jarman

unread,
Sep 12, 2019, 5:59:58 AM9/12/19
to Dart FFI
So the sample makefile is:


primitives: primitives.o
    gcc
-o a.out primitives.o

primitives
.o: primitives.c
    gcc
-c primitives.c

dylib
: primitives.o
    gcc
-dynamiclib -undefined suppress -flat_namespace primitives.o -o ../primitives.dylib

clean
:
    rm a
.out primitives.o ../primitives.dylib

The arm64 example is:

CC=gcc
CCARM
=arm-linux-gnueabihf-gcc
CCARM64
=aarch64-linux-gnu-gcc
CFLAGS
=-Wall -g -O -fPIC

# Bump this whenever the benchmark is updated.
VERSION
=1

.PHONY: all clean

all
: out/linux/x64/libnative_functions.so out/linux/ia32/libnative_functions.so out/linux/arm64/libnative_functions.so out/linux/arm/libnative_functions.so

cipd
:
    cipd create
-name dart/benchmarks/fficall -in out -install-mode copy -tag version:$(VERSION)

clean
:
    rm
-rf *.o *.so out

out/linux/arm64:
    mkdir
-p out/linux/arm64

out/linux/arm64/native_functions.o: native_functions.c | out/linux/arm64
    $
(CCARM64) $(CFLAGS) -c -o $@ native_functions.c

out/linux/arm64/libnative_functions.so: out/linux/arm64/native_functions.o
    $
(CCARM64) $(CFLAGS) -s -shared -o $@ out/linux/arm64/native_functions.o

How can this arm64 be used to generate the required dylib?

Samir Jindel

unread,
Sep 12, 2019, 6:46:47 AM9/12/19
to Craig Jarman, Dart FFI
It's not sufficient to create just the dylib on Mac. You need to create a `.framework`, which includes a code signature. This can be created via a separate Xcode project, and then you can follow the Wiki instructions to include that library.

However, a much simpler solution is to drop your sources into your app so they're loaded automatically and then use `DynamicLibrary.process` to access them.


--
You received this message because you are subscribed to the Google Groups "Dart FFI" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dart-ffi+u...@googlegroups.com.

Craig Jarman

unread,
Sep 12, 2019, 9:15:16 AM9/12/19
to Samir Jindel, Dart FFI
Thanks

The similar solution appeals to me.

To drop the source .c and .h files onto an app, for both android and iOS, does this mean including them under the lib directory?

And not bother with the makefile?

And then somehow call the file with the DynamicLibrary.process function.

Is there an example of how this is all structured?

This is for an open source third party library, such as with the ffi primitive example.

Samir Jindel

unread,
Sep 12, 2019, 9:20:30 AM9/12/19
to Craig Jarman, Dart FFI
Packaging native code with a Dart library is only streamlined for Flutter plugins on Android, Mac and iOS.

You should create your Dart library via `flutter create --template=plugin`.

This will create both an Xcode project and an Android Studio project inside your package where you can add the sources.

We don't have an example yet, but we'd be happy to make your plugin the example :)
Do you have a GitHub repo we can look at to help you better?

TZ Martin

unread,
Sep 12, 2019, 4:21:16 PM9/12/19
to Samir Jindel, Craig Jarman, Dart FFI
Lurking on this thread, but want to chime in support for an example as well.  I'm working on pretty much the same thing.  Thanks for everyone's input.

Message has been deleted
Message has been deleted
Message has been deleted

Craig Jarman

unread,
Sep 12, 2019, 10:14:24 PM9/12/19
to Dart FFI
Thank Samir

I'm now a little confused, however.

Re 
Can you just include your sources in the Xcode app directly then?

The source code is required for Android also.

Re:
It's not sufficient to create just the dylib on Mac. You need to create a `.framework`, which includes a code signature. This can be created via a separate Xcode project, and then you can follow the Wiki instructions to include that library.
However, a much simpler solution is to drop your sources into your app so they're loaded automatically and then use `DynamicLibrary.process` to access them. 

This simpler solution would be ideal, but it's not clear how to include the source C-code in a flutter app. Where should it be placed? How are the libraries referenced/imported etc?

From the examples, it seems a makefile is required, and this needs to be configured to output an arm64 file.

In Swift/Xcode it is simple, one creates a bridging header. And thats all.

Re
Packaging native code with a Dart library is only streamlined for Flutter plugins on Android, Mac and iOS.
You should create your Dart library via `flutter create --template=plugin`.
This will create both an Xcode project and an Android Studio project inside your package where you can add the sources.

If this is the recommended approach to address both iOS and Android, then that would be preferred.

Following this, my understanding now then, is that dropping the source code directly into the flutter app and then using `DynamicLibrary.process` to access them is not the ideal approach

Rather one should create a plugin.

For this plugin, from the documentation, it seems that there are three options:
  1. First Party Library
  2. Open Source 3rd party library
  3. Closed Source 3rd party library
Of these three options, the First Party Library represents the simplest approach.

Steps for creating a First Party Library are:
  1. New Dart Library -  Create a Dart library via `flutter create --template=plugin`. This creates both an Xcode project and an Android Studio project.
  2. Add Sources -  Add the sources inside the packages.
  3. Framework/iOS - Having added C sources to the Xcode project, add the prefix @_cdecl("myFunctionName")to the exported symbol declarations to ensure they are visible to Dart. See https://github.com/flutter/flutter/wiki/Binding-to-native-code-via-FFI#first-party-library
    1. Add Library/Framework - Add the "Embedded Binaries" and "Linked Frameworks & Libraries" section of the target in Xcode.
  4. Framework/Android - DynamicLibrary.open can be used to load a given API through providing the name. For example DynamicLibrary.open("libGLES_v3.so")
    1. No documentation provided as to how this library is implemented other than "The process for including native code in source or binary form is the same for an app or plugin". Possibly this is defined somewhere else.
I'm not sure if the above steps are correct. Rather I'm looking to confirm I've understood the documentation correctly.

I was under the assumption that a C-library could be included directly in a Flutter project, but that seems to either not be the case for flutter apps, or not recommended.



On Thursday, 12 September 2019 23:20:30 UTC+10, Samir Jindel wrote:
Packaging native code with a Dart library is only streamlined for Flutter plugins on Android, Mac and iOS.

You should create your Dart library via `flutter create --template=plugin`.

This will create both an Xcode project and an Android Studio project inside your package where you can add the sources.

We don't have an example yet, but we'd be happy to make your plugin the example :)
Do you have a GitHub repo we can look at to help you better?

Thanks

To unsubscribe from this group and stop receiving emails from it, send an email to dart...@googlegroups.com.

Samir Jindel

unread,
Sep 13, 2019, 3:45:23 AM9/13/19
to Craig Jarman, Dart FFI, Shams Zakhour
It's clear we need to improve the documentation and add an example.
We also need to get rid of the outdated documentation from the SQLite prototype.

To unsubscribe from this group and stop receiving emails from it, send an email to dart-ffi+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dart-ffi/a8264e22-5a8d-429a-8085-04ca369d539d%40googlegroups.com.

Craig Jarman

unread,
Sep 13, 2019, 3:53:15 AM9/13/19
to Samir Jindel, Dart FFI, Shams Zakhour
Yes, an example would help. Plus a set of steps.

Is it correct one needs to create a plugin?

Samir Jindel

unread,
Sep 13, 2019, 3:59:34 AM9/13/19
to Craig Jarman, Dart FFI, Shams Zakhour
I think that creating a plugin is the cleanest approach, but it's not strictly necessary.
We have made demos on Android and iOS by just adding the libraries directly, as on the Wiki page.
But I know the wiki page is unclear.

Craig Jarman

unread,
Sep 13, 2019, 4:05:41 AM9/13/19
to Samir Jindel, Dart FFI, Shams Zakhour
So with adding the libraries directly. Is there a need to compile the C code, to create the file?

A makefile is not required for consuming c-code from swift, but dart is different perhaps.

And, if so, do they need to be added to the flutter code, or included in the IOS and Android directory? Also, do these C libraries need to be complied for Arm64?





Sent from my iPhone

Samir Jindel

unread,
Sep 13, 2019, 4:35:50 AM9/13/19
to Craig Jarman, Dart FFI, Shams Zakhour
So with adding the libraries directly. Is there a need to compile the C code, to create the file?

The C code need to be compiled, but can be done in a few ways. Ideally, you should use Xcode (on iOS) and NDK (on Android).

 A makefile is not required for consuming c-code from swift, but dart is different perhaps.

There should be no need for a Makefile if you're using Xcode and NDK (although you may need a CMakeLists for NDK).

And, if so, do they need to be added to the flutter code, or included in the IOS and Android directory? Also, do these C libraries need to be complied for Arm64?

It depends on whether you want to link the code into your app statically or dynamically. On iOS, you can choose; on Android, you're forced to link it dynamically.
To do it dynamically, you should add the code to both the "ios" and "android" directories so that Xcode and NDK pick it up. 


Craig Jarman

unread,
Sep 13, 2019, 5:15:07 AM9/13/19
to Samir Jindel, Dart FFI, Shams Zakhour
Thanks again.

So all C code needs to be complied. But does it need to be precompiled to a .dylib before being added to Xcode and Android? It sounds like that’s not required afterall.

You mention there are a few ways if doing this, is there any particular approach documented for Xcode and Android? A plug-in is cleanest perhaps, but I’m happy to walk before running...

So steps are:
1. Add C-library to iOS and Android directory. Or is it a subdirectories if there two? For Xcode I’d expect the code to be placed under the runner directory. For Android I wouldn’t know.
2.  Create class and Import dart.FFI
3. ?? - Somehow imports and refer to the c-code, or precomplied .dynlib file. eg: 
final dylib = ffi.DynamicLibrary.open('primitives.dylib');
4. Compile app

It’s step 3 which is unclear, given that the primitives example doesn’t translate to the flutter app scenario.

On the wiki page it is stated:

Add the following prefix to the exported symbol declarations to ensure they are visible to Dart. The prefix being:

@_cdecl("myFunctionName")

So this prefix needs to be added to the C-Code? For dart to recognise the function? I presume this is the non-dylib option.




Craig Jarman

unread,
Sep 13, 2019, 5:20:09 AM9/13/19
to TZ Martin, Dart FFI
Have you had any luck getting this to work?

I’m not familiar with C code, but have managed to use a C-library from swift.

Now looking to do the same with dart/flutter.

Sent from my iPhone

Craig Jarman

unread,
Sep 17, 2019, 3:10:22 AM9/17/19
to Dart FFI
Hi again

I looked int creating a plugin for flutter

A plugin calls for a swift and java implementation and does not lend itself to being written in Dart. See https://flutter.dev/docs/development/packages-and-plugins/developing-packages

This approach would result is three code sets:
  1. Java > C-Library
  2. Swift > C-Library
  3. Dart to Plugin (Swift and Java)
This introduces a maintenance overhead, and negates the need for FFI  

Did you mean to recommend `flutter create --template=package` rather than `flutter create --template=plugin`? Or have I misunderstood something here?

Rather than a plugin the options seem to be:
  1. Go direct - Include the C-lib in the flutter project and have that be compiled to iOS or Android as part of the standard build.
  2. Implement a package - Include C-lib in a package and with dart headers.
If it were a package would that package need to reference a dynlib or framework? Or can you just include the C-source code?

Thanks



On Friday, 13 September 2019 17:59:34 UTC+10, Samir Jindel wrote:
I think that creating a plugin is the cleanest approach, but it's not strictly necessary.
We have made demos on Android and iOS by just adding the libraries directly, as on the Wiki page.
But I know the wiki page is unclear.

On Fri, Sep 13, 2019 at 9:53 AM Craig Jarman <craig....@gmail.com> wrote:
Yes, an example would help. Plus a set of steps.

Is it correct one needs to create a plugin?

On 13 Sep 2019, at 5:44 pm, Samir Jindel <sji...@google.com> wrote:

It's clear we need to improve the documentation and add an example.
We also need to get rid of the outdated documentation from the SQLite prototype.

--
You received this message because you are subscribed to the Google Groups "Dart FFI" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dart...@googlegroups.com.

Samir Jindel

unread,
Sep 17, 2019, 4:10:30 AM9/17/19
to Craig Jarman, Dart FFI
Hi Craig,

I did have a plugin in mind. Using the plugin infrastructure is important to ensure that the included C code is compiled with the right toolchain for the target platform (e.g. Xcode or NDK).

However, I imagine a layout like this:
  1. android/ -> contains C
  2. ios/ -> contains C
  3. Dart -> C directly
The method-channels aspect of the plugin would not be used. We'll have an example to illustrate this soon.

Could you please elaborate on your use case in particular?

Thanks,
Samir

To unsubscribe from this group and stop receiving emails from it, send an email to dart-ffi+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dart-ffi/5689105c-c442-46cb-8937-5783f46680df%40googlegroups.com.

Craig Jarman

unread,
Sep 17, 2019, 4:27:17 AM9/17/19
to Samir Jindel, Dart FFI
Thanks

My use case.

I’ve a C-Library used to calculate planetary motion and positions over time.

Currently an swift/iOS only app moving to Flutter.

For now, with flutter, one swift class, with three methods, serves as a wrapper for the method channel integration. The Android equivalent. Not yet implemented, would require a Java-based equivalent.

So, going forward, would the plungin include the c-code only? And somehow that flutter application recognises the library. As I presume Xcode for instance won’t compile Dart.

Thanks 

Craig Jarman

unread,
Sep 17, 2019, 7:15:29 AM9/17/19
to Dart FFI
Here is the C-Library. Plus the swift wrapper.



On Tuesday, 17 September 2019 18:10:30 UTC+10, Samir Jindel wrote:
Hi Craig,

I did have a plugin in mind. Using the plugin infrastructure is important to ensure that the included C code is compiled with the right toolchain for the target platform (e.g. Xcode or NDK).

However, I imagine a layout like this:
  1. android/ -> contains C
  2. ios/ -> contains C
  3. Dart -> C directly
The method-channels aspect of the plugin would not be used. We'll have an example to illustrate this soon.

Could you please elaborate on your use case in particular?

Thanks,
Samir

Renan Araujo

unread,
Sep 18, 2019, 5:59:28 PM9/18/19
to Dart FFI
I have a similar use case that can maybe help.
Bitmap package does a couple of transformations on ARBG32 bitmaps.  I was thinking into moving those heavy computations into a native (C) side.
Today it is a package, not a plugin.
https://github.com/renancaraujo/bitmap/

Craig Jarman

unread,
Sep 18, 2019, 6:26:33 PM9/18/19
to Renan Araujo, Dart FFI

Hey Renan

 

That would be similar.

 

As Samir has explained however, there is still a need for two compilation cycles and hence the plugin approach is recommend (one each for iOS and Android).

 

With plugin however there is typically some Java or Swift wrapper. I’m curious to know FFI removes the need for this, as XCode for one, won’t compile Dart code.

 

So that leave only the C-Lib in the package. I’m just guessing however.

To unsubscribe from this group and stop receiving emails from it, send an email to dart-ffi+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dart-ffi/f1ceceba-e8ab-4ac8-ae4e-bac21aa0501e%40googlegroups.com.

Samir Jindel

unread,
Sep 20, 2019, 9:36:21 AM9/20/19
to Craig Jarman, Renan Araujo, Dart FFI
I've updated the wiki to contain a complete, step-by-step walkthrough for creating the plugin:

Would you mind trying it out and seeing if it fits your use case?

Reply all
Reply to author
Forward
0 new messages