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.dylibThis 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.dartThis will generate swift_api_bindings.dart.
Finally, you can run the example using this command:
dart run example.dartThe 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:
- Swift classes become Objective-C interfaces, so include them using an
objCInterfacevisitor. - When
swiftccompiles the library, it gives the Objective-C interface a module prefix. Internally, ourSwiftClassis actually registered asswift_module.SwiftClass. So you need to tell FFIgen about this prefix usingnode.module. The module is whatever you passed toswiftcin the-module-nameflag.