Improving the Usability of C Libraries in Swift
The Swift code above has a very “C” feel to it. It has global function calls with prefixed names like
wgpuInstanceCreateSurfaceand global integer constants likeWGPUStatus_Error. It pervasively uses unsafe pointers, some of which are managed with explicit reference counting, where the user provides calls towpuXYZAddRefandwgpuXYZReleasefunctions. It works, but it doesn’t feel like Swift, and inherits various safety problems of C.Fortunately, we can improve this situation, providing a safer and more ergonomic interface to WebGPU from Swift that feels like it belongs in Swift. More importantly, we can do so without changing the WebGPU implementation: Swift provides a suite of annotations that you can apply to C headers to improve the way in which the C APIs are expressed in Swift. These annotations describe common conventions in C that match up with Swift constructs, projecting a more Swift-friendly interface on top of the C code.
[…]
The problem of needing to layer information on top of existing C headers is not a new one. As noted earlier, Swift relies on a Clang feature called API notes to let us express this same information in a separate file, so we don’t have to edit the header.
Previously:
- Swift Proposal: InlineArray
- C String Functions in Swift: a malloc’y Story
- C String Functions in Swift
- Swift Tip: OpaquePointer vs. UnsafePointer
- Swift Imports Fixed-size C Arrays As Tuples
- Unsafe Swift: Using Pointers and Interacting With C
- Passing an Array of Strings From Swift to C
- Swift and C Libraries
Update (2026-01-26): Tony Arnold:
I am really happy to see API notes documented here.
I used this on a shared C++/Swift project a few years back, and it massively improved the experience of writing code against the C++ types. It’s well worth the investment of your time to do this if you’re in a similar spot.
5 Comments RSS · Twitter · Mastodon
Never mind that—how do you call Swift-native API in C (without cooperation from the Swift code and/or tedious linking to the ABI, obviously)? I hate to burden my Swift-loving friends with my appalling preference for archaic and insecure languages, but sometimes you gotta do what you gotta do, and increasingly Apple's API is now Swift-only, including stuff that should certainly have C interface like testing APFS filesystem flags.
@Michael I was thinking of testing sparsity of files, but it turns out that I was wrong and it's accessible through kCFURLIsSparseKey. So Swift is just benefiting from better foundation types, although I wonder in that case how foundation implements the sparsity check, whether that's blessed kernel knowledge, or what a POSIX-ish C coder would be expected to do, which is to compare an estimate of the logical and allocated sizes, an imprecise heuristic.
@Michael Thanks, indeed, that is where it should be, and I really can't think why I didn't find it at the time, perhaps it wasn't documented then. The apple online manpage is, of course, totally outdated, but it's been documented since at least Sonoma.