Skip to content

Conversation

@DougGregor
Copy link
Member

Here is a draft blog post on improving the usability of C libraries in Swift using header annotations or API notes. I use the WebGPU headers as an example.


There are many interesting, useful, and fun C libraries in the software ecosystem. While one could go and rewrite these libraries in Swift, usually there is no need, because Swift provides direct interoperability with C. With a little setup, you can directly use existing C libraries from your Swift code.

When you use a C library directly from Swift, it will look and feel similar to using it from C. That can be useful if you're following sample code or a tutorial written in C, but it can also feel out-of-place. For example, here's a small amount of code using a C API:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
When you use a C library directly from Swift, it will look and feel similar to using it from C. That can be useful if you're following sample code or a tutorial written in C, but it can also feel out-of-place. For example, here's a small amount of code using a C API:
When you use a C library directly from Swift, it will look and feel similar to using it from C. That can be useful if you're following sample code or a tutorial written in C, but it can also feel out of place. For example, here's a small amount of code using a C API:

{
"compilerVersion": "Apple Swift version 6.2 (swiftlang-6.2.2.15.4 clang-1700.3.15.2)",
"target": {
"triple": "arm64-apple-macosx15.0",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't match the triple you used above, ie arm64-apple-macos14.


Fortunately, we can improve this situtation, 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.

In this post, I'm going to leverage these annotations to improve how Swift interacts with WebGPU. By the end, we'll be able to take advantage of Swift features like argument labels, methods, enums, and automatic reference counting, like this:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In this post, I'm going to leverage these annotations to improve how Swift interacts with WebGPU. By the end, we'll be able to take advantage of Swift features like argument labels, methods, enums, and automatic reference counting, like this:
In this post, I'm going to use these annotations to improve how Swift interacts with the WebGPU C code. By the end, we'll be able to take advantage of Swift features like argument labels, methods, enums, and automatic reference counting, like this:


I'm going to do it from the command line, using `swift-synthesize-interface`. From the directory containing `webgpu.h` and `module.modulemap`, run:

```swift
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

swift-synthesize-interface isn't in the path by default - so maybe mention you'll either need an open source toolchain on your path, or prefix the command with xcrun to use the command with the version of Swift that Xcode provides.

} WGPUAdapterType WGPU_ENUM_ATTRIBUTE;
```

will be translated into:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
will be translated into:
is translated into:

public var WGPUAdapterType_Force32: WGPUAdapterType { get }
```

and there will be lots of global functions like this:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
and there will be lots of global functions like this:
and there are lots of global functions like this:

}
```

The easiest thing to do is to put `module.modulemap` alongside the header itself. For my experiment here, I put it in the root direction of my `webgpu-headers` checkout. If you're in a Swift package, put it into its own target with this layout:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be “root directory” instead of “root direction”.

@@ -0,0 +1,341 @@
#! swift -enable-bare-slash-regex

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2025 Apple Inc. and the Swift.org project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Swift.org project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

I think this'll sort of the license/soundness check in CI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants