on
Bridging Rust to Swift, pt. 2: cbindgen
We concluded our previous post with building a C compatible library which could be accessed from C/Swift - with the caveat that we needed to provide the appropriate header files.
Hold on (for one more day)?
Headers? Our rust code doesn’t have any C style header files to describe its public API. Nor does rust need them. But, in order to access the library from a C environment, we are going to have to provide one. This header file should contain the interface that is represented by all the exported functions in our rust code. While we could write one manually, it’s much easier to have one generated for us.
Enter cbindgen
cbindgen generates C/C++11 headers for
Rust libraries that expose a public C API. We had tagged these by prefixing pub
unsafe extern "C"
to their Rust definitions. Complete documentation
tocbindgen
can be found
here. A short primer
on using it follows.
Installing cbindgen
is as simple as running cargo install --force cbindgen
.
The force
argument simply updates it to the latest version if it’s already
installed. Once installed, we can either run it during our build process or as a
standalone program.
Run as standalone program
Let’s download the template config
.toml file from the
cbindgen
code respository. For our current project, most of the defaults
should be fine. Let’s switch the language for the generated header file to
C
from C++
.
Run cbindgen --output swift_bridged.h
from the root of our rust project. If
all goes well, we should have a nice header file generated with the following
content.
Run with build script
We could alternatively have the C header file generated automatically when we
build our Rust project. We can use a cbindgen.toml
file, like the one above,
to configure cbindgen
with a build script, like the one below. Alternatively,
it could be configured using a Builder interface.
Finally, we need to add cbindgen
as a build dependency via cargo add --build
cbindgen
. This adds the latest version of cbindgen
as a build dependency on
our rust project. Run cargo build
, and we should have an identical header file
to one generated by the standalone program.
Choosing between the standalone program or build script is largely a matter of choice on how we want to distribute the header file. In the next post, we will look at building binary frameworks to make accessing the C library easier.