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 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
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:
- 'third_party/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.