tree: e501612e5b28f9f81e7d9a94c71b7e4efb017d0a [path history] [tgz]
  1. config.yaml
  2. example.dart
  3. pubspec.yaml
  4. README.md
  5. swift_api.h
  6. swift_api.swift
  7. swift_api_bindings.dart
example/swift/README.md

Swift example

This example shows how to use ffigen to interact with Swift libraries.

Swift APIs can be made compatible with Objective-C, using the @objc annotation. Then you can use the swiftc tool to build a dylib for the library using -emit-library, and generate an Objective-C wrapper header using -emit-objc-header-path filename.h:

swiftc -c swift_api.swift               \
    -module-name swift_module           \
    -emit-objc-header-path swift_api.h  \
    -emit-library -o libswiftapi.dylib

This should generate libswiftapi.dylib and swift_api.h. For more information about Objective-C / Swift interoperability, see the Apple documentation.

Once you have an Objective-C wrapper header, ffigen can parse it like any other header:

dart run ffigen --config config.yaml

This will generate swift_api_bindings.dart, using the config in the ffigen section of the pubspec.yaml.

Finally, you can run the example using this command:

dart run example.dart

Config notes

Ffigen only sees the Objective-C wrapper header, swift_api.h. So you need to set the language to objc, and set the entry-point to the header:

language: objc
headers:
  entry-points:
    - 'swift_api.h'

Swift classes become Objective-C interfaces, so include them like this:

objc-interfaces:
  include:
    - 'SwiftClass'

There is one extra option you need to set when wrapping a Swift library. When swiftc compiles the library, it gives the Objective-C interface a module prefix. Internally, our SwiftClass is actually registered as swift_module.SwiftClass. So you need to tell ffigen about this prefix, so it loads the correct class from the dylib:

objc-interfaces:
  include:
    - 'SwiftClass'
  module:
    'SwiftClass': 'swift_module'

The module prefix is whatever you passed to swiftc in the -module-name flag.