SkillAgentSearch skills...

Ffigen

FFI binding generator

Install / Use

/learn @dart-archive/Ffigen
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

This package has moved!

The package can now be found at https://github.com/dart-lang/native/tree/main/pkgs/ffigen


pub package Build Status Coverage Status

Binding generator for FFI bindings.

Note: ffigen only supports parsing C headers, not C++ headers.

This bindings generator can be used to call C code -- or code in another language that compiles to C modules that follow the C calling convention -- such as Go or Rust. For more details, see: https://dart.dev/guides/libraries/c-interop

ffigen also has experimental support for calling ObjC and Swift code; for details see: https://dart.dev/guides/libraries/objective-c-interop

Example

For some header file example.h:

int sum(int a, int b);

Add configurations to Pubspec File:

ffigen:
  output: 'generated_bindings.dart'
  headers:
    entry-points:
      - 'example.h'

Output (generated_bindings.dart).

import 'dart:ffi' as ffi;
class NativeLibrary {
  final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
      _lookup;
  NativeLibrary(ffi.DynamicLibrary dynamicLibrary)
      : _lookup = dynamicLibrary.lookup;
  NativeLibrary.fromLookup(
      ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
          lookup)
      : _lookup = lookup;

  int sum(int a, int b) {
    return _sum(a, b);
  }

  late final _sumPtr = _lookup<ffi.NativeFunction<ffi.Int Function(ffi.Int, ffi.Int)>>('sum');
  late final _sum = _sumPtr.asFunction<int Function(int, int)>();
}
}

Using this package

  • Add ffigen under dev_dependencies in your pubspec.yaml (run dart pub add -d ffigen).
  • Add package:ffi under dependencies in your pubspec.yaml (run dart pub add ffi).
  • Install LLVM (see Installing LLVM).
  • Configurations must be provided in pubspec.yaml or in a custom YAML file (see configurations).
  • Run the tool- dart run ffigen.

Jump to FAQ.

Installing LLVM

package:ffigen uses LLVM. Install LLVM (9+) in the following way.

Linux

  1. Install libclangdev.

    With apt-get: sudo apt-get install libclang-dev.

    With dnf: sudo dnf install clang-devel.

Windows

  1. Install Visual Studio with C++ development support.
  2. Install LLVM or winget install -e --id LLVM.LLVM.

MacOS

  1. Install Xcode.
  2. Install Xcode command line tools - xcode-select --install.
  3. Install LLVM - brew install llvm.

Configurations

Configurations can be provided in 2 ways-

  1. In the project's pubspec.yaml file under the key ffigen.
  2. Via a custom YAML file, then specify this file while running - dart run ffigen --config config.yaml

The following configuration options are available-

<table> <thead> <tr> <th>Key</th> <th>Explaination</th> <th>Example</th> </tr> <colgroup> <col> <col style="width: 100px;"> </colgroup> </thead> <tbody> <tr> <td>output<br><i><b>(Required)</b></i></td> <td>Output path of the generated bindings.</td> <td>
output: 'generated_bindings.dart'

or

output:
  bindings: 'generated_bindings.dart'
  ... 
</td> </tr> <tr> <td>llvm-path</td> <td>Path to <i>llvm</i> folder.<br> ffigen will sequentially search for `lib/libclang.so` on linux, `lib/libclang.dylib` on macOs and `bin\libclang.dll` on windows, in the specified paths.<br><br> Complete path to the dynamic library can also be supplied.<br> <i>Required</i> if ffigen is unable to find this at default locations.</td> <td>
llvm-path:
  - '/usr/local/opt/llvm'
  - 'C:\Program Files\llvm`
  - '/usr/lib/llvm-11'
  # Specify exact path to dylib
  - '/usr/lib64/libclang.so'
</td> </tr> <tr> <td>headers<br><i><b>(Required)</b></i></td> <td>The header entry-points and include-directives. Glob syntax is allowed.<br> If include-directives are not specified ffigen will generate everything directly/transitively under the entry-points.</td> <td>
headers:
  entry-points:
    - 'folder/**.h'
    - 'folder/specific_header.h'
  include-directives:
    - '**index.h'
    - '**/clang-c/**'
    - '/full/path/to/a/header.h'
</td> </tr> <tr> <td>name<br><i>(Prefer)</i></td> <td>Name of generated class.</td> <td>
name: 'SQLite'
</td> </tr> <tr> <td>description<br><i>(Prefer)</i></td> <td>Dart Doc for generated class.</td> <td>
description: 'Bindings to SQLite'
</td> </tr> <tr> <td>compiler-opts</td> <td>Pass compiler options to clang. You can also pass these via the command line tool.</td> <td>
compiler-opts:
  - '-I/usr/lib/llvm-9/include/'

and/or via the command line -

dart run ffigen --compiler-opts "-I/headers
-L 'path/to/folder name/file'"
</td> </tr> <tr> <td>compiler-opts-automatic -> macos -> include-c-standard-library</td> <td>Tries to automatically find and add C standard library path to compiler-opts on macos.<br> <b>Default: true</b> </td> <td>
compiler-opts-automatic:
  macos:
    include-c-standard-library: false
</td> </tr> <tr> <td> functions<br><br>structs<br><br>unions<br><br>enums<br><br> unnamed-enums<br><br>macros<br><br>globals </td> <td>Filters for declarations.<br><b>Default: all are included.</b><br><br> Options -<br> - Include/Exclude declarations.<br> - Rename declarations.<br> - Rename enum and struct members.<br> - Expose symbol-address for functions and globals.<br> </td> <td>
functions:
  include: # 'exclude' is also available.
    # Matches using regexp.
    - [a-z][a-zA-Z0-9]*
    # '.' matches any character.
    - prefix.*
    # Matches with exact name
    - someFuncName
    # Full names have higher priority.
    - anotherName
  rename:
    # Regexp groups based replacement.
    'clang_(.*)': '$1'
    'clang_dispose': 'dispose'
    # Removes '_' from beginning.
    '_(.*)': '$1'
  symbol-address:
    # Used to expose symbol address.
    include:
      - myFunc
structs:
  rename:
    # Removes prefix underscores
    # from all structures.
    '_(.*)': '$1'
  member-rename:
    '.*': # Matches any struct.
      # Removes prefix underscores
      # from members.
      '_(.*)': '$1'
enums:
  rename:
    # Regexp groups based replacement.
    'CXType_(.*)': '$1'
  member-rename:
    '(.*)': # Matches any enum.
      # Removes '_' from beginning
      # enum member name.
      '_(.*)': '$1'
    # Full names have higher priority.
    'CXTypeKind':
      # $1 keeps only the 1st
      # group i.e only '(.*)'.
      'CXType(.*)': '$1'
globals:
  exclude:
    - aGlobal
  rename:
    # Removes '_' from
    # beginning of a name.
    '_(.*)': '$1'
</td> </tr> <tr> <td>typedefs</td> <td>Filters for referred typedefs.<br><br> Options -<br> - Include/Exclude (referred typedefs only).<br> - Rename typedefs.<br><br> Note: Typedefs that are not referred to anywhere will not be generated. </td> <td>
typedefs:
  exclude:
    # Typedefs starting with `p` are not generated.
    - 'p.*'
  rename:
    # Removes '_' from beginning of a typedef.
    '_(.*)': '$1'
</td> </tr> <tr> <td>functions -> expose-typedefs</td> <td>Generate the typedefs to Native and Dart type of a function<br> <b>Default: Inline types are used and no typedefs to Native/Dart type are generated.</b> </td> <td>
functions:
  expose-typedefs:
    include:
      # Match function name.
      - 'myFunc'
       # Do this to expose types for all function.
      - '.*'
    exclude:
      # If you only use exclude, then everything
      # not excluded is generated.
      - 'dispose'
</td> </tr> <tr> <td>functions -> leaf</td> <td>Set isLeaf:true for functions.<br> <b>Default: all functions are excluded.</b> </td> <td>
functions:
  leaf:
    include:
      # Match function name.
      - 'myFunc'
       # Do this to set isLeaf:true for all functions.
      - '.*'
    exclude:
      # If you only use exclude, then everything
      # not excluded is generated.
      - 'dispose'
</td> </tr> <tr> <td>functions -> variadic-arguments</td> <td>Generate multiple functions with different variadic arguments.<br> <b>Default: var args for any function are ignored.</b> </td> <td>
functions:
  variadic-arguments:
    myfunc:
      // Native C types are supported
      - [int, unsigned char, long*, float**]
      // Common C typedefs (stddef.h) are supported too
      - [uint8_t, intptr_t, size_t, wchar_t*]
      // Structs/Unions/Typedefs from generated code or a library import can be referred too.
      - [MyStruct*, my_custom_lib.CustomUnion]
</td> </tr> <tr> <td>structs -> pack</td> <td>Override the @Packed(X) annotation for generated structs.<br><br> <i>Options - none, 1, 2, 4, 8, 16</i><br> You can use RegExp to match with the <b>generated</b> names.<br><br> Note: Ffigen can only reliably identify packing specified using __attribute__((__packed__)). However, structs packed using `#pragma pack(...)` or any other way could <i>potentially</i> be incorrect in which case you can override the generated annotations. </td> <td>
structs:
  pack:
    # Matches with the generated name.
    'NoPackStruct': none # No packing
    '.*': 1 # Pack all structs with value 1
</td> </tr> <tr
View on GitHub
GitHub Stars360
CategoryDevelopment
Updated23d ago
Forks54

Languages

Dart

Security Score

80/100

Audited on Mar 9, 2026

No findings