All Projects โ†’ brickpop โ†’ Flutter Rust Ffi

brickpop / Flutter Rust Ffi

Licence: other
Starter project for Flutter plugins willing to access native and synchronous rust code using FFI

Programming Languages

rust
11053 projects
dart
5743 projects

Projects that are alternatives of or similar to Flutter Rust Ffi

Android Camera2 Secret Picture Taker
Take pictures ๐Ÿ“ท secretly (without preview or launching device's camera app) using Android CAMERA2 API
Stars: โœญ 275 (-16.67%)
Mutual labels:  mobile, native
Firebase Instagram
๐Ÿ“ธ Instagram clone with Firebase Cloud Firestore, Expo, and React Native ๐Ÿ˜๐Ÿ˜
Stars: โœญ 389 (+17.88%)
Mutual labels:  mobile, native
Navigation
Scene-Based Navigation for React and React Native
Stars: โœญ 350 (+6.06%)
Mutual labels:  mobile, native
Expo
An open-source platform for making universal native apps with React. Expo runs on Android, iOS, and the web.
Stars: โœญ 15,550 (+4612.12%)
Mutual labels:  mobile, native
Titanium mobile
๐Ÿš€ Native iOS- and Android- Apps with JavaScript
Stars: โœญ 2,553 (+673.64%)
Mutual labels:  mobile, native
Share Api Polyfill
A polyfill for the sharing that can be used in desktop too, so your users can shere in their twitter, facebook, messenger, linkedin, sms, e-mail, print, telegram or whatsapp.
Stars: โœญ 210 (-36.36%)
Mutual labels:  mobile, native
Nat Explorer
An example project using Nat & Weex.
Stars: โœญ 55 (-83.33%)
Mutual labels:  mobile, native
Keen Slider
The HTML touch slider carousel with the most native feeling
Stars: โœญ 3,097 (+838.48%)
Mutual labels:  mobile, native
Nat
A powerful kit for adding native functionalities to your weex app.
Stars: โœญ 294 (-10.91%)
Mutual labels:  mobile, native
Babylonnative
Build cross-platform native applications with the power of the Babylon.js JavaScript framework
Stars: โœญ 299 (-9.39%)
Mutual labels:  native
React Native Dom
An experimental, comprehensive port of React Native to the web.
Stars: โœญ 3,247 (+883.94%)
Mutual labels:  native
Blog
๐Ÿ“– ไธชไบบๅšๅฎข๏ผŒๅˆ†ไบซไธ€ไบ›ๅ‰็ซฏๅทฅไฝœๅญฆไน ไธญ็š„ๆ”ถ่Žท๏ผŒๆฌข่ฟŽ โœจ๏ผŒๅšๅฎขๅœฐๅ€>>
Stars: โœญ 297 (-10%)
Mutual labels:  native
Remoto
Ultra-simple RPC ecosystem designed for right now.
Stars: โœญ 304 (-7.88%)
Mutual labels:  mobile
Open Source Xamarin Apps
๐Ÿ“ฑ Collaborative List of Open Source Xamarin Apps
Stars: โœญ 318 (-3.64%)
Mutual labels:  mobile
Ultimate Python Resource Hub
The Ultimate resource hub of Python: All at one place
Stars: โœญ 298 (-9.7%)
Mutual labels:  mobile
Vant
Lightweight Mobile UI Components built on Vue
Stars: โœญ 18,852 (+5612.73%)
Mutual labels:  mobile
Thera
Thera is an integrated development environment(IDE) powered by Alibaba.com aimed for improving mobile hybrid solution develop experience, such as weex, luaview, react native.
Stars: โœญ 298 (-9.7%)
Mutual labels:  mobile
Status React
a free (libre) open source, mobile OS for Ethereum
Stars: โœญ 3,307 (+902.12%)
Mutual labels:  mobile
Cordova Plugin Device
Apache Cordova Plugin device
Stars: โœญ 327 (-0.91%)
Mutual labels:  mobile
React Native Carplay
CarPlay with React Native
Stars: โœญ 321 (-2.73%)
Mutual labels:  native

Flutter Rust FFI Template

This project is a Flutter Plugin template.

It provides out-of-the box support for cross-compiling native Rust code for all available iOS and Android architectures and call it from plain Dart using Foreign Function Interface.

This template provides first class FFI support, the clean way.

  • No Swift/Kotlin wrappers
  • No message passing
  • No async/await on Dart
  • Write once, use everywhere
  • No garbage collection
  • Mostly automated development
  • No need to export aar bundles or .framework's

Getting started

Write your native code

Edit your code within rust/src/lib.rs and add any dependencies you need.

Make sure to annotate your exported functions with #[no_mangle] and pub extern so the function names can be matched from Dart.

Returning strings or structs may require using unsafe blocks. Returned strings or structs will need to be free'd from Dart.

Compile the library

  • Make sure that the Android NDK is installed
    • You might also need LLVM from the SDK manager
  • Ensure that the env variable $ANDROID_NDK_HOME points to the NDK base folder
    • It may look like /Users/brickpop/Library/Android/sdk/ndk-bundle on MacOS
    • And look like /home/brickpop/dev/android/ndk-bundle on Linux
  • On the rust folder:
    • Run make to see the available actions
    • Run make init to install the Rust targets
    • Run make all to build the libraries and the .h file
  • Update the name of your library in Cargo.toml
    • You'll need to update the symlinks to target the new file names. See iOS and Android below.

Generated artifacts:

  • Android libraries
    • target/aarch64-linux-android/release/libexample.so
    • target/armv7-linux-androideabi/release/libexample.so
    • target/i686-linux-android/release/libexample.so
    • target/x86_64-linux-android/release/libexample.so
  • iOS library
    • target/universal/release/libexample.a
  • Bindings header
    • target/bindings.h

Reference the shared objects

iOS

Ensure that ios/mylib.podspec includes the following directives:

...
   s.source           = { :path => '.' }
+  s.public_header_files = 'Classes**/*.h'
   s.source_files = 'Classes/**/*'
+  s.static_framework = true
+  s.vendored_libraries = "**/*.a"
   s.dependency 'Flutter'
   s.platform = :ios, '8.0'
...

On flutter/ios, place a symbolic link to the libexample.a file

$ cd flutter/ios
$ ln -s ../rust/target/universal/release/libexample.a .

Append the generated function signatures from rust/target/bindings.h into flutter/ios/Classes/MylibPlugin.h

$ cd flutter/ios
$ cat ../rust/target/bindings.h >> Classes/MylibPlugin.h

In our case, it will append char *rust_greeting(const char *to); and void rust_cstr_free(char *s);

NOTE: By default, XCode will skip bundling the libexample.a library if it detects that it is not being used. To force its inclusion, add dummy invocations in SwiftMylibPlugin.swift that use every single native function that you use from Flutter:

...
  public func dummyMethodToEnforceBundling() {
    rust_greeting("...");
    compress_jpeg_file("...");
    compress_png_file("...");
    // ...
    // This code will force the bundler to use these functions, but will never be called
  }
}

If you won't be using Flutter channels, the rest of methods can be left empty.

Note: Support for avmv7, armv7s and i386 is deprecated. The targets can still be compiled with Rust 1.41 or earlier and by uncommenting the make init line on rust/makefile

Android

Similarly as we did on iOS with libexample.a, create symlinks pointing to the binary libraries on rust/target.

You should have the following structure on flutter/android for each architecture:

src
โ””โ”€โ”€ main
    โ””โ”€โ”€ jniLibs
        โ”œโ”€โ”€ arm64-v8a
        โ”‚   โ””โ”€โ”€ [email protected] -> ../../../../../rust/target/aarch64-linux-android/release/libexample.so
        โ”œโ”€โ”€ armeabi-v7a
        โ”‚   โ””โ”€โ”€ [email protected] -> ../../../../../rust/target/armv7-linux-androideabi/release/libexample.so
        โ”œโ”€โ”€ x86
        โ”‚   โ””โ”€โ”€ [email protected] -> ../../../../../rust/target/i686-linux-android/release/libexample.so
        โ””โ”€โ”€ x86_64
            โ””โ”€โ”€ [email protected] -> ../../../../../rust/target/x86_64-linux-android/release/libexample.so

As before, if you are not using Flutter channels, the methods within android/src/main/kotlin/org/mylib/mylib/MylibPlugin.kt can be left empty.

Exposing a Dart API to use the bindings

To invoke the native code: load the library, locate the symbols and typedef the Dart functions. You can automate this process from rust/target/bindings.h or do it manually.

Automatic binding generation

To use ffigen, add the dependency in pubspec.yaml.

 dev_dependencies:
   flutter_test:
     sdk: flutter
+  ffigen: ^1.2.0

Also, add the following lines at the end of pubspec.yaml:

ffigen:
  output: lib/bindings.dart
  headers:
    entry-points:
    - rust/target/bindings.h
  name: GreeterBindings
  description: Dart bindings to call mylib functions

On MacOS:

brew install llvm
flutter pub run ffigen:setup -I/usr/local/opt/llvm/include -L/usr/local/opt/llvm/lib

On Linux:

sudo apt-get install -y clang libclang-dev
flutter pub run ffigen:setup

Generate lib/bindings.dart:

flutter pub run ffigen

Finally, use the generated GreetingBindings class. An example wrapper is available here.

Manual bindings

Load the library:

final DynamicLibrary nativeExampleLib = Platform.isAndroid
    ? DynamicLibrary.open("libexample.so")   // Load the dynamic library on Android
    : DynamicLibrary.process();              // Load the static library on iOS

Find the symbols we want to use, with the appropriate Dart signatures:

final Pointer<Utf8> Function(Pointer<Utf8>) rustGreeting = nativeExampleLib
    .lookup<NativeFunction<Pointer<Utf8> Function(Pointer<Utf8>)>>("rust_greeting")
    .asFunction();

final void Function(Pointer<Utf8>) freeGreeting = nativeExampleLib
    .lookup<NativeFunction<Void Function(Pointer<Utf8>)>>("rust_cstr_free")
    .asFunction();

Call them:

// Prepare the parameters
final name = "John Smith";
final Pointer<Utf8> namePtr = Utf8.toUtf8(name);
print("- Calling rust_greeting with argument:  $namePtr");

// Call rust_greeting
final Pointer<Utf8> resultPtr = rustGreeting(namePtr);
print("- Result pointer:  $resultPtr");

final String greetingStr = Utf8.fromUtf8(resultPtr);
print("- Response string:  $greetingStr");

When we are done using greetingStr, tell Rust to free it, since the Rust implementation kept it alive for us to use it.

freeGreeting(resultPtr);

More information

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].