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 third_party/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 tool/ffigen.dart
This will generate swift_api_bindings.dart.
Finally, you can run the example using this command:
dart run example.dart
The FFIgen configuration is defined in tool/ffigen.dart. FFIgen only sees the Objective-C wrapper header, swift_api.h. So you need to enable Objective-C support and set the entry-point to the header.
final generator = FfiGenerator( output: Output( dart: DartOutput(path: packageRoot.resolve('swift_api_bindings.dart')), ), objectiveC: const ObjectiveC(), input: Input(entryPoints: [packageRoot.resolve('third_party/swift_api.h')]), visitors: [ Visitor( objCInterface: (node) { if (node.name == 'SwiftClass') { node.isIncluded = true; node.module = 'swift_module'; } }, ), ], );
There are two important things to note about this example:
objCInterface visitor.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 using node.module. The module is whatever you passed to swiftc in the -module-name flag.