blob: 62f10789dbfcd8f220f02c073a207784925309f9 [file] [view] [edit]
# 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`:
```shell
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](https://developer.apple.com/documentation/swift/importing-swift-into-objective-c).
Once you have an Objective-C wrapper header, FFIgen can parse it like
any other header:
```shell
dart run tool/ffigen.dart
```
This will generate [swift_api_bindings.dart](./swift_api_bindings.dart).
Finally, you can run the example using this command:
```shell
dart run example.dart
```
## Config notes
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.
<!-- file://./tool/ffigen.dart#generator -->
```dart
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:
1. Swift classes become Objective-C interfaces, so include them using an
`objCInterface` visitor.
2. 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
using `node.module`. The module is whatever you passed to `swiftc` in the
`-module-name` flag.