-
Notifications
You must be signed in to change notification settings - Fork 255
Proposed blog post: Improving the usability of C libraries in Swift #1255
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Proposed blog post: Improving the usability of C libraries in Swift #1255
Conversation
|
|
||
| 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: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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", |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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 |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| will be translated into: | |
| is translated into: |
| public var WGPUAdapterType_Force32: WGPUAdapterType { get } | ||
| ``` | ||
|
|
||
| and there will be lots of global functions like this: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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: |
There was a problem hiding this comment.
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 | |||
|
|
|||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| //===----------------------------------------------------------------------===// | |
| // | |
| // 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
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.