mirror of
https://github.com/logos-messaging/nim-ffi.git
synced 2026-06-21 00:40:16 +00:00
A SwiftPM package wrapping the timer library's native ABI behind an idiomatic `TimerNode` Swift class. `build-xcframework.sh` cross-compiles the Nim library to a static MyTimer.xcframework with three slices — ios-arm64 (device), ios-arm64-simulator, and macos-arm64 — assembling the .xcframework by hand so it works without a functioning Simulator toolchain (CI-friendly). The wrapper bridges the async FFI-thread callback to a synchronous Swift API with a semaphore and reads the typed EchoResponse struct out of the callback. The macos-arm64 slice makes the wrapper testable on the host: `swift test` passes against it. Device/simulator slices are the real iOS deployment artifacts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
iOS example — Swift over the native C ABI
A SwiftPM package that wraps the timer library's native (zero-serialization)
C ABI behind an idiomatic Swift class, TimerNode. The library is cross-compiled
to a static .xcframework and consumed from Swift; struct returns come back as
typed Swift values.
let node = try TimerNode(name: "my-app")
print(try node.version()) // "nim-timer v0.1.0"
let r = try node.echo("hello", delayMs: 5) // EchoResult
print(r.echoed, r.timerName)
Layout
| Path | Description |
|---|---|
build-xcframework.sh |
Cross-compiles the Nim lib to MyTimer.xcframework (ios-arm64 device, ios-arm64 simulator, macos-arm64) and bundles the C headers + module map. |
cheaders/ |
The native C header (my_timer.h), CBOR header, and module.modulemap (module CMyTimer). |
Sources/MyTimer/MyTimer.swift |
The Swift wrapper. Bridges the async FFI-thread callback to a synchronous Swift API with a semaphore; reads the typed EchoResponse struct out of the callback. |
Package.swift |
SwiftPM: a binary target (the xcframework) + the Swift wrapper + tests. |
Tests/ |
Unit tests, runnable on the host via the macOS slice. |
Build & test
cd examples/timer/ios
./build-xcframework.sh # builds the 3 slices into MyTimer.xcframework
swift test # runs on the host (macos-arm64 slice)
build-xcframework.sh assembles the .xcframework directly (no
xcodebuild -create-xcframework), so it works in headless / CI environments.
The macos-arm64 slice exists only so the wrapper is testable with
swift test; real iOS deployment uses the ios-arm64 (device) and
ios-arm64-simulator slices.
Use it in an iOS app
- Run
./build-xcframework.sh. - Add this directory as a local Swift package (Xcode → Add Package
Dependencies… → Add Local…), or depend on it in your own
Package.swift. import MyTimerand useTimerNode.
Notes
- This is the native, same-process path — the app links the library directly.
The CBOR ABI is for inter-process communication only (see
../ipc). - Each call is dispatched on the library's background FFI thread;
TimerNodeblocks on a semaphore until the result callback fires. A struct return (e.g.EchoResponse) is read inside the callback — it is valid only for the callback's lifetime — and copied into the returned Swift value. - Regenerate
cheaders/my_timer.hfrom the repo root withnimble genbindings_cif the library's API changes.