FFI binding generator

Related tags

Desktop ffigen
Overview

pub package Build Status Coverage Status

Binding generator for FFI bindings.

Note: ffigen only supports parsing C headers.

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).

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

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

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

Using this package

  • Add ffigen under dev_dependencies in your pubspec.yaml (run dart pub add -d ffigen).
  • 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.

ubuntu/linux

  1. Install libclangdev - sudo apt-get install libclang-dev.

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

Key Explaination Example
output
(Required)
Output path of the generated bindings.
output: 'generated_bindings.dart'
llvm-path Path to llvm folder.
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.

Complete path to the dynamic library can also be supplied.
Required if ffigen is unable to find this at default locations.
llvm-path:
  - '/usr/local/opt/llvm'
  - 'C:\Program Files\llvm`
  - '/usr/lib/llvm-11'
  # Specify exact path to dylib
  - '/usr/lib64/libclang.so'
headers
(Required)
The header entry-points and include-directives. Glob syntax is allowed.
If include-directives are not specified ffigen will generate everything directly/transitively under the entry-points.
headers:
  entry-points:
    - 'folder/**.h'
    - 'folder/specific_header.h'
  include-directives:
    - '**index.h'
    - '**/clang-c/**'
    - '/full/path/to/a/header.h'
name
(Prefer)
Name of generated class.
name: 'SQLite'
description
(Prefer)
Dart Doc for generated class.
description: 'Bindings to SQLite'
compiler-opts Pass compiler options to clang. You can also pass these via the command line tool.
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'"
compiler-opts-automatic -> macos -> include-c-standard-library Tries to automatically find and add C standard library path to compiler-opts on macos.
Default: true
compiler-opts-automatic:
  macos:
    include-c-standard-library: false
functions

structs

unions

enums

unnamed-enums

macros

globals
Filters for declarations.
Default: all are included.

Options -
- Include/Exclude declarations.
- Rename declarations.
- Rename enum and struct members.
- Expose symbol-address for functions and globals.
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'
typedefs Filters for referred typedefs.

Options -
- Include/Exclude (referred typedefs only).
- Rename typedefs.

Note: Typedefs that are not referred to anywhere will not be generated.
typedefs:
  exclude:
    # Typedefs starting with `p` are not generated.
    - 'p.*'
  rename:
    # Removes '_' from beginning of a typedef.
    '_(.*)': '$1'
functions -> expose-typedefs Generate the typedefs to Native and Dart type of a function
Default: Inline types are used and no typedefs to Native/Dart type are generated.
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'
functions -> leaf Set isLeaf:true for functions.
Default: all functions are excluded.
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'
structs -> pack Override the @Packed(X) annotation for generated structs.

Options - none, 1, 2, 4, 8, 16
You can use RegExp to match with the generated names.

Note: Ffigen can only reliably identify packing specified using __attribute__((__packed__)). However, structs packed using `#pragma pack(...)` or any other way could potentially be incorrect in which case you can override the generated annotations.
structs:
  pack:
    # Matches with the generated name.
    'NoPackStruct': none # No packing
    '.*': 1 # Pack all structs with value 1
comments Extract documentation comments for declarations.
The style and length of the comments recognized can be specified with the following options-
style: doxygen(default) | any
length: brief | full(default)
If you want to disable all comments you can also pass
comments: false.
comments:
  style: any
  length: full
structs -> dependency-only

unions -> dependency-only
If `opaque`, generates empty `Opaque` structs/unions if they were not included in config (but were added since they are a dependency) and only passed by reference(pointer).
Options - full(default) | opaque
structs:
  dependency-only: opaque
unions:
  dependency-only: opaque
sort Sort the bindings according to name.
Default: false, i.e keep the order as in the source files.
sort: true
use-supported-typedefs Should automatically map typedefs, E.g uint8_t => Uint8, int16_t => Int16 etc.
Default: true
use-supported-typedefs: true
dart-bool Should generate dart `bool` instead of Uint8 for c99 bool in functions.
Default: true
dart-bool: true
use-dart-handle Should map `Dart_Handle` to `Handle`.
Default: true
use-dart-handle: true
preamble Raw header of the file, pasted as-it-is.
preamble: |
  // ignore_for_file: camel_case_types, non_constant_identifier_names
typedef-map Map typedefs to Native Types.
Values can only be Void, Uint8, Int8, Uint16, Int16, Uint32, Int32, Uint64, Int64, IntPtr, Float and Double.
typedef-map:
  'my_custom_type': 'IntPtr'
  'size_t': 'Int64'
size-map Size of integers to use (in bytes).
The defaults (see example) may not be portable on all OS. Do not change these unless absolutely sure.
# These are optional and also default,
# Omitting any and the default
# will be used.
size-map:
  char: 1
  unsigned char: 1
  short: 2
  unsigned short: 2
  int: 4
  unsigned int: 4
  long: 8
  unsigned long: 8
  long long: 8
  unsigned long long: 8
  enum: 4

Limitations

  1. Multi OS support for types such as long. Issue #7

Trying out examples

  1. cd examples/<example_u_want_to_run>, Run dart pub get.
  2. Run dart run ffigen.

Running Tests

  1. Dynamic library for some tests need to be built before running the examples.
  2. cd test/native_test.
  3. Run dart build_test_dylib.dart.

Run tests from the root of the package with dart run test.

Note: If llvm is not installed in one of the default locations, tests may fail.

FAQ

Can ffigen be used for removing underscores or renaming declarations?

Ffigen supports regexp based renaming, the regexp must be a full match, for renaming you can use regexp groups ($1 means group 1).

E.g - For renaming clang_dispose_string to string_dispose. We can can match it using clang_(.*)_(.*) and rename with $2_$1.

Here's an example of how to remove prefix underscores from any struct and its members.

structs:
  ...
  rename:
    '_(.*)': '$1' # Removes prefix underscores from all structures.
  member-rename:
    '.*': # Matches any struct.
      '_(.*)': '$1' # Removes prefix underscores from members.

How to generate declarations only from particular headers?

The default behaviour is to include everything directly/transitively under each of the entry-points specified.

If you only want to have declarations directly particular header you can do so using include-directives. You can use glob matching to match header paths.

headers:
  entry-points:
    - 'path/to/my_header.h'
  include-directives:
    - '**my_header.h' # This glob pattern matches the header path.

Can ffigen filter declarations by name?

Ffigen supports including/excluding declarations using full regexp matching.

Here's an example to filter functions using names

functions:
  include:
    - 'clang.*' # Include all functions starting with clang.
  exclude:
    - '.*dispose': # Exclude all functions ending with dispose.

This will include clang_help. But will exclude clang_dispose.

Note: exclude overrides include.

How does ffigen handle C Strings?

Ffigen treats char* just as any other pointer,(Pointer<Int8>). To convert these to/from String, you can use package:ffi. Use ptr.cast<Utf8>().toDartString() to convert char* to dart string and "str".toNativeUtf8() to convert string to char*.

How does ffigen handle C99 bool data type?

Although dart:ffi doesn't have a NativeType for bool, they can be implemented as Uint8. Ffigen generates dart bool for function parameters and return type by default. To disable this, and use int instead, set dart-bool: false in configurations.

How are unnamed enums handled?

Unnamed enums are handled separately, under the key unnamed-enums, and are generated as top level constants.

Here's an example that shows how to include/exclude/rename unnamed enums

unnamed-enums:
  include:
    - 'CX_.*'
  exclude:
    - '.*Flag'
  rename:
    'CXType_(.*)': '$1'

Why are some struct/union declarations generated even after excluded them in config?

This happens when an excluded struct/union is a dependency to some included declaration. (A dependency means a struct is being passed/returned by a function or is member of another struct in some way)

Note: If you supply structs -> dependency-only as opaque ffigen will generate these struct dependencies as Opaque if they were only passed by reference(pointer).

structs:
  dependency-only: opaque
unions:
  dependency-only: opaque

How to expose the native pointers?

By default the native pointers are private, but you can use the symbol-address subkey for functions/globals and make them public by matching with its name. The pointers are then accesible via nativeLibrary.addresses.

Example -

functions:
  symbol-address:
    include:
      - 'myFunc' # Match function name.
      - '.*' # Do this to expose all function pointers.
    exclude: # If you only use exclude, then everything not excluded is generated.
      - 'dispose'

How to get typedefs to Native and Dart type of a function?

By default these types are inline. But you can use the expose-typedef subkey for functions to generate them. This will expose the Native and Dart type. E.g - for a function named hello, the generated typedefs are named as NativeHello and DartHello.

Example -

functions:
  expose-typedefs:
    include:
      - 'myFunc' # Match function name.
      - '.*' # Do this to expose types for all function.
    exclude: # If you only use exclude, then everything not excluded is generated.
      - 'dispose'

How are Structs/Unions/Enums that are reffered to via typedefs handled?

Named declarations use their own names even when inside another typedef. However, unnamed declarations inside typedefs take the name of the first typedef that refers to them.

Why are some typedefs not generated?

The following typedefs are not generated -

  • They are not referred to anywhere in the included declarations.
  • They refer to a struct/union having the same name as itself.
  • They refer to a boolean, enum, inline array, Handle or any unsupported type.

What are these logs generated by ffigen and how to fix them?

Ffigen can sometimes generate a lot of logs, especially when it's parsing a lot of code.

  • SEVERE logs are something you definitely need to address. They can be caused due to syntax errors, or more generally missing header files (which need to be specified using compiler-opts in config)
  • WARNING logs are something you can ignore, but should probably look into. These are mostly indications of declarations ffigen couldn't generate due to limitations of dart:ffi, private declarations (which can be resolved by renaming them via ffigen config) or other minor issues in the config file itself.
  • Everything else can be safely ignored. It's purpose is to simply let you know what ffigen is doing.
  • The verbosity of the logs can be changed by adding a flag with the log level. E.g - dart run ffigen --verbose <level>. Level options are - [all, fine, info (default), warning, severe]. The all and fine will print a ton of logs are meant for debugging purposes only.
Comments
  • Sharing shared definitions

    Sharing shared definitions

    Consider the following scenario:

    • header1 - with a struct
    • header2 which imports header1 - having that struct in a signature
    • header3 which imports header1 - having also that struct in the signature

    Now we run the generator on header 2 and 3: they both generate the same struct. These two structs will be Dart classes with the same name but incompatible. You can work around that with Pointer.cast<>(), but that's not safe. Also, this increases code size.

    It would be better to be able to run the generator on all 3 headers files and let the generated files for header 2 and 3 import the generated file for header 1.

    We need to think about a good design for this, especially if headers 2 and 3 are in different dart packages.

    (I am not sure how common this scenario is. For example libclang and sqlite3 stand very much on themselves. But I can imagine structs defined in OS APIs fall into this category, so it would be nice to address this.)

    enhancement 
    opened by dcharkes 25
  • Support size_t, int, and other common C types // platform independent bindings

    Support size_t, int, and other common C types // platform independent bindings

    We should support generating some dart:ffi type for size_t, int, long, etc., when dart:ffi starts supporting this: https://github.com/dart-lang/sdk/issues/36140.

    Example

    Comparing generated files on Linux x64 and MacOS x64 which uses size_t:

    CINDEX_LINKAGE const char *clang_getFileContents(CXTranslationUnit tu,
                                                     CXFile file, size_t *size);
    
     typedef _c_clang_getFileContents = ffi.Pointer<ffi.Int8> Function(
       ffi.Pointer<CXTranslationUnitImpl> tu,
       ffi.Pointer<ffi.Void> file,
    -  ffi.Pointer<ffi.Uint64> size,
    +  ffi.Pointer<ffi.Int32> size,
     );
    

    The lack of 'named' integer types that vary in size on different platforms currently makes ffigen only generate correct bindings for its host platform. In order to make ffigen generate platform independent bindings we should address this issue.

    waiting-on-dart-ffi 
    opened by dcharkes 20
  • Missing types without SEVERE message

    Missing types without SEVERE message

    When commented out compiler-opts according to https://github.com/dart-lang/ffigen/issues/190#issuecomment-800778965, struct io_service_t and mach_port_t are missing

    diff --git a/macos/IOKit.yaml b/macos/IOKit.yaml
    index 9c7a916..0404501 100644
    --- a/macos/IOKit.yaml
    +++ b/macos/IOKit.yaml
    @@ -1,9 +1,9 @@
     name: IOKit
     description: Bindings to `IOKit.h`.
     output: 'lib/src/macos/iokit.dart'
    -compiler-opts: '-I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Kernel.framework/Headers/'
    +# compiler-opts: '-I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Kernel.framework/Headers/'
     headers:
    
    @@ -228,8 +228,6 @@ class IOHIDDeviceRef extends ffi.Opaque {}
    
     class CFAllocatorRef extends ffi.Opaque {}
    
    -class io_service_t extends ffi.Opaque {}
    -
     class CFStringRef extends ffi.Opaque {}
    
     class IOHIDManagerRef extends ffi.Opaque {}
    @@ -238,8 +236,6 @@ class CFDictionaryRef extends ffi.Opaque {}
    
     class CFSetRef extends ffi.Opaque {}
    
    -class mach_port_t extends ffi.Opaque {}
    -
     const int kIOReturnSuccess = 0;
    
     const String kIOServicePlane = 'IOService';
    

    Reproduce

    Repo: https://github.com/Sunbreak/logic_conf.dart Branch: https://github.com/Sunbreak/logic_conf.dart/tree/reproduce/kernel-headers

    % flutter2.0.x pub run ffigen --config macos/IOKit.yaml
    Running in Directory: '/Users/sunbreak/Sunbreak/logic_conf.dart'
    Input Headers: [macos/IOKit_.h]
    Finished, Bindings generated in /Users/sunbreak/Sunbreak/logic_conf.dart/lib/src/macos/iokit.dart
    

    Envrionment

    Flutter: Flutter 2.0.6 OS: Mac OS X 10.15.7

    flutter doctor -v
    [✓] Flutter (Channel stable, 2.0.6, on Mac OS X 10.15.7 19H1713 darwin-x64, locale en-CN)
        • Flutter version 2.0.6 at /Users/sunbreak/google/flutter-2.0.x
        • Framework revision 1d9032c7e1 (9 months ago), 2021-04-29 17:37:58 -0700
        • Engine revision 05e680e202
        • Dart version 2.12.3
        • Pub download mirror https://pub.flutter-io.cn
        • Flutter download mirror https://storage.flutter-io.cn
    
    [✗] Android toolchain - develop for Android devices
        ✗ Unable to locate Android SDK.
          Install Android Studio from: https://developer.android.com/studio/index.html
          On first launch it will assist you in installing the Android SDK components.
          (or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).
          If the Android SDK has been installed to a custom location, please use
          `flutter config --android-sdk` to update to that location.
    
    
    [✗] Xcode - develop for iOS and macOS
        ✗ Xcode installation is incomplete; a full installation is necessary for iOS development.
          Download at: https://developer.apple.com/xcode/download/
          Or install Xcode via the App Store.
          Once installed, run:
            sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
            sudo xcodebuild -runFirstLaunch
        ✗ CocoaPods not installed.
            CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side.
            Without CocoaPods, plugins will not work on iOS or macOS.
            For more info, see https://flutter.dev/platform-plugins
          To install see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.
    
    [✗] Chrome - develop for the web (Cannot find Chrome executable at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome)
        ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.
    
    [!] Android Studio (not installed)
        • Android Studio not found; download from https://developer.android.com/studio/index.html
          (or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).
    
    [✓] VS Code (version 1.64.0)
        • VS Code at /Applications/Visual Studio Code.app/Contents
        • Flutter extension version 3.34.0
    
    [!] Connected device
        ! No devices available
    
    ! Doctor found issues in 5 categories.
    
    opened by Sunbreak 17
  • Unsound Null-Safety

    Unsound Null-Safety

    We currently do not support sound null safety (added by #122).

    Tasks Remaining:

    • [x] Migrate all dependencies
      • [x] Args
      • [x] logging
      • [x] cli_util
      • [x] glob
      • [x] pub_semver
    • [x] Remove all --no-sound-null-safety flags.
    opened by mannprerak2 16
  • Add option to expose function pointers & typedefs

    Add option to expose function pointers & typedefs

    For some users it might be useful to expose the function pointers instead of Dart wrapper functions. In the use case where they want to pass these function pointers to C.

    We should probably have a similar exclude/include mechanism specifying which functions should be exposed as function pointers.

    opened by dcharkes 14
  • C uintptr_t is being mapped to ffi.UnsignedLong instead of ffi.UIntPtr

    C uintptr_t is being mapped to ffi.UnsignedLong instead of ffi.UIntPtr

    Hello. I discovered unexpected behavior

    temp.h

    #include <stdint.h>
    
    uintptr_t temp_u();
    intptr_t temp_i();
    

    using ffigen on linux I get this.

    ...
      int temp_u() {
        return _temp_u();
      }
    
      late final _temp_uPtr =
          _lookup<ffi.NativeFunction<uintptr_t Function()>>('temp_u');
      late final _temp_u = _temp_uPtr.asFunction<int Function()>();
    
      int temp_i() {
        return _temp_i();
      }
    
      late final _temp_iPtr =
          _lookup<ffi.NativeFunction<ffi.IntPtr Function()>>('temp_i');
      late final _temp_i = _temp_iPtr.asFunction<int Function()>();
      
      typedef uintptr_t = ffi.UnsignedLong;
    ...
    

    for some reason intptr_t converts correctly to ffi.IntPtr but uintptr_t is converted to typedef uintptr_t = ffi.UnsignedLong; Why is uintptr_t not converted to ffi.UIntPtr?

    ffi.UnsignedLong is 64 for linux but 32 for windows, which causes errors when using generated dart code by linux on windows.

    opened by rogurotus 13
  • how to solve

    how to solve "symbol lookup error: undefined symbol"?????

    If liba depends on libb, when I call the liba functions, it wiil be error "symbol lookup error: undefined symbol". Becase the liba function calls libb function. Thanks!

    opened by fayfive 12
  • Automatic ref counting for ObjC objects

    Automatic ref counting for ObjC objects

    The basic idea is to add retain and release flags to the constructor of our Dart wrapper objects for ObjC. If retain is true, it calls objc_retain. If release is true, it registers the wrapper object with a NativeFinalizer that calls objc_release when the wrapper is GC'd.

    The wrapper object is constructed at the return site of methods that return an ObjC object, so at that point we have to decide whether to retain and/or release the object. The retain flag should be enabled when method doesn't automatically increment the ref count of the returned object (ie, when the user doesn't own the returned reference). So the only time we don't manually call retain is when we already own the returned reference (eg due to new or alloc calls), which means that our wrapper object always owns the reference it holds. Therefore, the release flag should pretty much always be enabled (disabling it creates a weak reference, and we don't really have a use case for that atm).

    This probably doesn't handle all the edge cases correctly, but it's a good enough start. One major missing piece is there are annotations that affect this. But we can handle those in follow up CLs as needed.

    Fixes #351 Fixes #305

    opened by liamappelbe 11
  • Question: How to generate bindings for multiple libs, where lib A depends on lib B?

    Question: How to generate bindings for multiple libs, where lib A depends on lib B?

    Is there a recommended approach for generating bindings for multiple libs, where lib A depends on lib B? The best workaround I have found so far is to generate the bindings for each lib separately, and then write wrapper functions around the generated functions from lib A that use the proper types from lib B.

    For example, I am generating bindings for libsecret. libsecret makes use of glib. Below is the definition of one of the core functions from libsecret.

    gboolean    secret_password_storev_sync    (const SecretSchema *schema,
      GHashTable *attributes,
      const gchar *collection,
      const gchar *label,
      const gchar *password,
      GCancellable *cancellable,
      GError **error);
    

    with a config below

    output: 'lib/src/generated/libsecret.dart'
    name: 'Libsecret'
    description: 'Bindings to libsecret'
    headers:
      entry-points:
        - '<path_to_libsecret>/libsecret/libsecret/secret.h'
        - '<path_to_libsecret>/libsecret/libsecret/secret-schema.h'
        - '<path_to_libsecret>/libsecret/libsecret/secret-password.h'
    

    The following is generated:

    int secret_password_storev_sync(
      ffi.Pointer<SecretSchema> schema,
      ffi.Pointer<ffi.Int32> attributes,
      ffi.Pointer<ffi.Int32> collection,
      ffi.Pointer<ffi.Int32> label,
      ffi.Pointer<ffi.Int32> password,
      ffi.Pointer<ffi.Int32> cancellable,
      ffi.Pointer<ffi.Pointer<ffi.Int32>> error,
    ) {...}
    

    This isn't really what I would hope, since gchar, GHashTable, etc. are all represented as Int32 here.

    If I add the following to the config

    compiler-opts:
    - '-I/<path_to_glib>/'
    

    I get the following:

    int secret_password_storev_sync(
      ffi.Pointer<SecretSchema> schema,
      ffi.Pointer<GHashTable> attributes,
      ffi.Pointer<gchar> collection,
      ffi.Pointer<gchar> label,
      ffi.Pointer<gchar> password,
      ffi.Pointer<ffi.Int32> cancellable,
      ffi.Pointer<ffi.Pointer<GError>> error,
    )
    

    This is great, except for one issue. GHashTable, gchar, etc. are part of the generated Libsecret lib. This isn't a huge deal for the types, but glib has functions as well, which also get created as part of the generated Libsecret lib.

    The work around I am using currently is to generate the bindings separately, and then write a wrapper function like so:

    void wrapped_secret_password_storev_sync(
      Pointer<SecretSchema> schema,
      Pointer<GHashTable> attributes,
      Pointer<gchar> collection,
      Pointer<gchar> label,
      Pointer<gchar> password,
      Pointer<Int32> cancellable,
      Pointer<Pointer<GError>> error,
    ) {
        libsecret.secret_password_storev_sync(
          schema,
          attributes.cast(),
          collection.cast(),
          label.cast(),
          password.cast(),
          cancellable,
          error.cast(),
        );
      }
    

    This works, but is sort of tedious. Is there a better approach?

    opened by Jordan-Nelson 11
  • Generating Unions

    Generating Unions

    Hi, I apologise if there is already an issue for this, but either Google isn't being helpful, or I don't understand enough of the terminology to know what I'm looking at.

    I'm in the process of trying to write bindings for SDL, and I'm running into issues.

    SDL uses a union SDL_Event, and obviously ffigen isn't generating it.

    From my research, it seems as though Union support is coming, but certainly hasn't filtered down to 2.13 as of yet. Is this true? Is there a way I can test the latest ffigen if I switch to Flutter Master?

    Thanks in advance.

    opened by chrisnorman7 11
  • Nested structs

    Nested structs

    Closes #4

    • support for nested structs
    • Updated readme, changelog, test
    • Minor changes to remove null usage from code.

    Thanks to @jpnurmi for this(#126).

    opened by mannprerak2 11
  • Support variadic functions

    Support variadic functions

    We'll be adding support for variadic functions to dart:ffi:

    • https://github.com/dart-lang/sdk/issues/38578

    One interesting thing to think about is how this would work for bindings generation from .h files: It wouldn't know what specific var-args signature to use when generating method(s) for a vararg method. Either it could generate a lookup of pointer and require users to fp.asFunction or one would need to specify in the configuration.

    Originally posted by @mkustermann in https://github.com/dart-lang/sdk/issues/38578#issuecomment-1369696674

    Generating the function pointer would always require a cast, because a Pointer<NativeFunction<X Function(X, VarArgs(X, X))>> can't have the right signature. So it should probably be a Pointer<Void> if we go for that option. Which would result in:

    somePointer.cast<NativeFunction<...>>.asFunction<...>();
    

    However, that would not allow us to ever use variadic functions with static linking (@FfiNative) through ffigen.

    Moreover, that requires the user to both write out the C type and Dart type of both the non-variadic arguments and variadic arguments.

    So, I believe it would be better to specify the variadic arguments wanted in the config. That way the user only has to write out the C types, and only for the variadic arguments (not for the arguments before the ...).

    Also, since Dart doesn't have overloading, we would need to invent names if we want a function more than once. Adding a number is a bad idea, because when adding a variadic args config it might renumber, maybe we can default to appending the variadic argument types? Or default to appending the variadic argument types if there's more than one config?

    functions:
      variadic-arguments:
        'printf':
          - [uint32_t, double] # Single config generates `printf`.
    
    functions:
      variadic-arguments:
        'printf':
          - [uint32_t, double] # Generates `printfUInt32Double`.
          - [uint32_t, char*]  # Generates `printfUInt32CharPointer`.
    
    functions:
      variadic-arguments:
        'printf':
          - [uint32_t, double] # Generates `printfUInt32Double`.
          - types: [uint32_t, char*]
            postfix: 'IntString' # Generates `printfIntString`.
    

    Related issue:

    • https://github.com/dart-lang/ffigen/issues/182

    @mannprerak2 @mkustermann @Sunbreak WDYT? Any alternative ideas?

    enhancement waiting-on-dart-ffi 
    opened by dcharkes 5
  • C-style functions consuming Objective-C classes should allow the Objective-C class to be passed

    C-style functions consuming Objective-C classes should allow the Objective-C class to be passed

    A function declaration like:

    void foo(NSDate *date);
    

    Generates this code:

    void foo(ffi.Pointer<ObjCObject> date) {
      ...
    }
    

    Instead, it could generate code like:

    void foo(NSDate date) {
      ...
    }
    

    Or at least there should be an option or variant that accepts the NSDate.

    objective c 
    opened by brianquinlan 1
  • Missing iOS file when generating bindings for CMPedometer

    Missing iOS file when generating bindings for CMPedometer

    Hi! I'm trying to use generate bindings for the CMPedometer class that's part of the CoreMotion framework. But, I am just getting a blank bindings file.

    Config:

    name: PedometerBindings
    description: "Bindings for CM pedometer"
    language: objc
    output: 'lib/pedometer_bindings_generated.dart'
    compiler-opts:
      - '-F/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks'
    objc-interfaces:
      include:
        - "CMPedometer"
    headers:
      entry-points:
        - "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/CoreMotion.framework/Headers/CMPedometer.h"
    
    

    There are a series of Nullability Issue warnings, such as:

    [SEVERE] :     /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdlib.h:361:13: warning: pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified) [Nullability Issue]
    

    As well as a Lexical or Preprocessor Issue:

    [SEVERE] :     /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSURL.h:10:9: fatal error: 'Foundation/NSURLHandle.h' file not found [Lexical or Preprocessor Issue]
    

    Sorry in advance if I am missing something!!

    opened by leighajarett 15
  • Find LLVM logic should check architecture on Mac

    Find LLVM logic should check architecture on Mac

    On M1 chips, we can have a mismatch between arm64 and x64 architectures. We should take that into account when trying to find a libclang to open.

    See:

    • https://github.com/flutter/flutter/issues/116332
    opened by dcharkes 0
  • Add a common code path for config files used in tests

    Add a common code path for config files used in tests

    Many tests have code like the following that's used to generate a config file from a yaml string: https://github.com/dart-lang/ffigen/blob/master/test/collision_tests/decl_type_name_collision_test.dart#L21-L30.

    Funnelling these through a single code path would make it easier to experiment with changes to the config spec, as codemods could be applied in a single place during testing.

    Also, Google's internal use of ffigen requires changes to the file paths for the header files used in tests, and this would decrease the maintenance burden of those changes

    enhancement 
    opened by TzviPM 0
Owner
Dart
Dart is an open-source, scalable programming language, with robust libraries and runtimes, for building web, server, and mobile apps.
Dart
JavaScriptCore for Flutter use dart:ffi.

flutter_jscore JavaScriptCore for Flutter. The plugin provides the ability to evaluate JavaScript programs from within dart. Demo Screen recording Apk

KnoYo 131 Jan 3, 2023
A material theme editor and generator for Flutter to configure and preview the overall visual theme of your material app

A material theme editor and generator for Flutter to configure and preview the overall visual theme of your material app

Joshua 301 Jan 3, 2023
Aris wasmjsextend - Binding generator for FFI bindings

Binding generator for FFI bindings. Note: ffigen only supports parsing C headers

Behruz Hurramov 1 Jan 9, 2022
Binding and high-level wrapper on top of libssh - The SSH library!

Dart Binding to libssh version 0.9.6 binding and high-level wrapper on top of libssh - The SSH library! libssh is a multiplatform C library implementi

Isaque Neves 2 Dec 20, 2021
Mpv dart - MPV player's JSON IPC binding for Dart

MPV Dart MPV Player's JSON-IPC binding for Dart (Flutter Supported) Installation

Kingkor Roy Tirtho 11 Nov 24, 2022
This plugin create a binding between your translations from .arb files and your Flutter app.

PROJECT MAINTENANCE PAUSED This project is no longer maintained due to the lack of time and availability. I'm a developer to and I know how frustratin

Razvan Lung 255 Dec 3, 2022
Startup-Name-Generator-App-in-Flutter - Business Startup Name Generator App in Flutter

Business Startup Name Generator App #About APP: A simple mobile app that generat

AHSAN SIDDZ 0 Jan 30, 2022
Dart wrapper via dart:ffi for https://github.com/libusb/libusb

libusb Dart wrapper via dart:ffi for https://github.com/libusb/libusb Environment Windows(10) macOS Linux(Ubuntu 18.04 LTS) Usage Checkout example Fea

Woodemi Co., Ltd 28 Dec 20, 2022
Dart port for artwork-extractor using FFI

A simple library to extract & save artwork of a ?? music/audio file. This library is using a artwork-extractor library by alexmercerind. It is super s

null 3 Feb 23, 2022
A Dart FFI package to send 💬 toasts on Windows. Written in C++, based on WinToast.

desktoasts A Dart package to send native ?? toasts on Windows. Installation For Flutter dependencies: ... desktoasts: ^0.0.2 For Dart CLI here Sup

Hitesh Kumar Saini 37 Mar 7, 2022
A Dart FFI package to send 💬 toasts on Windows. Written in C++, based on WinToast.

desktoasts A Dart package to send native ?? toasts on Windows. Installation For Flutter dependencies: ... desktoasts: ^0.0.2 For Dart CLI here Sup

Hitesh Kumar Saini 37 Mar 7, 2022
JavaScriptCore for Flutter use dart:ffi.

flutter_jscore JavaScriptCore for Flutter. The plugin provides the ability to evaluate JavaScript programs from within dart. Demo Screen recording Apk

KnoYo 131 Jan 3, 2023
This Flutter plugin created to show how to use OpenCV and ZXing C++ libraries natively in Flutter with Dart FFI using the camera stream

OpenCV and ZXing C++ libraries natively in Flutter with Dart FFI using the camera stream

Khoren Markosyan 17 Oct 21, 2022
Pdfium_bindings - This project aims to wrap the complete Pdfium API in dart, over FFI

Pdfium_bindings - This project aims to wrap the complete Pdfium API in dart, over FFI

Isaque Neves 7 Oct 22, 2022
Flutter FFI+WebAssembly Example

flutter_ffi_plugin A new flutter plugin project. FFI # Remove Codesign on macos codesign --remove-signature /usr/local/bin/dart # Install cmake brew

Rody Davis 33 Oct 22, 2022
Starter project for Flutter plugins willing to access native and synchronous rust code using FFI

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 a

Jør∂¡ 561 Dec 7, 2022
A revolutionary new browser. HTML to Flutter transpiler. Written in Go (using Dart FFI) and Flutter.

Flutter Browser An experimental HTML & CSS to Flutter transpiler written in Go, using Dart FFI and Flutter. Screenshots Notice This works great for si

Mitja 12 Oct 24, 2022
A code generator to write widgets as function without loosing the benefits of classes.

Widgets are cool. But classes are quite verbose: class Foo extends StatelessWidget { final int value; final int value2; const Foo({Key key, thi

Remi Rousselet 528 Dec 29, 2022
Starter project and code generator for Flutter/Redux

Flutter Redux Starter/Code Generator Videos Short video ~ 1 minute Long video ~ 10 minutes We're using this approach to develop the Flutter app for In

Hillel Coren 278 Dec 12, 2022
Environment specific config generator for Dart and Flutter applications during CI/CD builds

Environment Config Generator Environment specific config generator. Allows to specify env configuration during CI/CD build. Primarily created to simpl

Denis Beketsky 86 Dec 2, 2022