This is the first day of my participation in the Gwen Challenge in November. Check out the details: the last Gwen Challenge in 2021

What is the

Dart FFI is a technique for calling C code on Dart mobile, command line, and server applications running on the Dart Native platform. Simply put, Dart and C call each other. Dart FFI is released as a stable version after Dart2.12.0 (included with Flutter 2.0 and later versions).

After all, the Dart language became popular because of the use of Flutter, so Dart FFI technology is more powerful for Flutter applications

Problem solved

  1. C API can be called synchronously, unlike a Flutter Channel which starts asynchronously
  2. C calls are faster, unlike the previous need to transfer via Native (or change the Flutter engine code).
  3. It is also possible to encapsulate and replace a Flutter Channel for faster and synchronized purposes

Simple to use

In order to see only FFI’s features, I will leave them out of the Flutter platform and just use the Dart application on the command line. My engineering environment:

Running environment MacOS 10.15.6

GCC 12.0.0

Cmake 3.20.1

Make 3.81

The dart 2.14.2

1. Create projects

Because the project structure is simple, create the project manually

1). Create pubspec.yaml file

2). Create the bin/main.dart file

3). Create C environment, create library, library/build folder

C, library/sample.h, library/sample.def, cmakelists.txt files

The directory structure is as follows

|_ bin
    |_ main.dart
|_ library
    |_ build
    |_ CMakeLists.txt
    |_ sample.c
    |_ sample.h
    |_ sample.def
|_ pubspec.yaml
Copy the code

2. Pubspec. yaml introduces FFI

Add the FFI and PATH libraries to dependencies in the pubspec.yaml file

pubspec.yaml

name: ffi_sample
version: 0.01.
description: Examples using FFI and FFIGen

publish_to: none

environment:
  sdk: "> = 2.12.0 < 3.0.0"

dependencies:
  path: ^ 1.7.0
  ffi: ^ 1.1.2
Copy the code

3. Compile C code

Write a simple function in sample.h

sample.h

void hello_world(a);
Copy the code

Implemented in sample.c

sample.c

#include <stdio.h>
#include <stdlib.h>
#include "sample.h"
void hello_world(a)
{
    printf("Hello World\n");
}
Copy the code

Simple export in sample.def

LIBRARY   sample
EXPORTS
   sample
Copy the code

Write and compile using cmakelists.txt file

Cmake_minimum_required (VERSION 3.7 FATAL_ERROR) Project (Sample_Library VERSION 1.0.0 LANGUAGES C) add_library(sample_library SHARED sample.c sample.def) add_executable(sample_test sample.c) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 17) set_target_properties(sample_library PROPERTIES PUBLIC_HEADER sample.h VERSION ${PROJECT_VERSION} SOVERSION 1 OUTPUT_NAME "sample" XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Hex_Identity_ID_Goes_Here" )Copy the code

3. Compile the C file

Now that you have all the files in place, you can compile your C code.

1). Go to the library/build folder

2). Execute cmake.. Generate the files required for compilation

3). Execute make compilation

cd library/build
cmake ..
make
Copy the code

If the libsample.1.0.0.dylib file is generated in the library/build folder, the compilation is successful.

4. Write Dart communication code

Call C in bin/main.dart

import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'dart:io' show Platform, Directory;

import 'package:path/path.dart' as path;

void main() {
  void main() {
  // Initialize the intermodulation framework
  var libraryPath =
      path.join(Directory.current.path, 'ibrary'.'build'.'libsample.so');
  if (Platform.isMacOS) {
    libraryPath = path.join(
        Directory.current.path, 'library'.'build'.'libsample.dylib');
  }
  if (Platform.isWindows) {
    libraryPath =
        path.join(Directory.current.path, 'library'.'Debug'.'libsample.dll');
  }
  final dylib = DynamicLibrary.open(libraryPath);

  // *************** 1. Dart calls C **************
  final Pointer<T> Function<T extends NativeType>(String symbolName)
      _lookup;
    _lookup = dylib.lookup;

  late final _hello_worldPtr =
      _lookup<NativeFunction<Void Function() > > ('hello_world');
  late final _hello_world = _hello_worldPtr.asFunction<void Function(a) > ();// Call the C method (no arguments)
  _hello_world();
}
Copy the code

5. Run code

Now run it from the project root on the command line

dart run bin/main.dart
Copy the code

If the output

Hello World
Copy the code

Call successful

conclusion

The above is a simple example of THE Dart FFI. I will continue to update it later to introduce the use of THE Dart FFI in detail. Welcome to follow. I packed all the above code into Github, Github address