Skip to content

Py-Swift/PySwiftKit

Repository files navigation

PySwiftKit

Swift Python Platform License

PySwiftKit is a powerful Swift Package Manager library for bidirectional Python-Swift interoperability. It uses Swift macros to generate Python C API bindings, enabling seamless communication between Swift and Python code.

✨ Features

  • πŸ”„ Bidirectional Binding - Call Swift from Python and Python from Swift
  • 🎯 Swift Macros - Automatic binding generation with @PyClass, @PyModule, @PyMethod
  • πŸ”€ Type Conversion - Automatic marshalling of common types (Int, String, Array, Dictionary, etc.)
  • ⚑ Performance - Direct C API integration with efficient GIL management
  • πŸ›‘οΈ Type Safety - Full Swift type system support with generic conversions
  • πŸ“± iOS & macOS - Support for iOS 13+ and macOS 11+
  • 🐍 Python 3.13 - Compatible with the latest Python version

πŸ“¦ Installation

Swift Package Manager

Add PySwiftKit to your Package.swift:

dependencies: [
    .package(url: "https://github.com/Py-Swift/PySwiftKit", from: "313.1.1")
]

Requirements

  • Swift: 5.0+ (Swift 6.0 tools)
  • Python: 3.13+
  • Platforms: iOS 13+, macOS 11+

πŸš€ Quick Start

Hello World Example

Swift Code:

import PySwiftWrapper

@PyClass
class HelloWorld {
    @PyInit
    init() {}
    
    @PyMethod
    func sendString(text: String) {
        print("Swift received: \(text)")
    }
}

@PyModule
struct HelloWorldModule: PyModuleProtocol {
    static var py_classes: [any (PyClassProtocol & AnyObject).Type] = [
        HelloWorld.self
    ]
}

Python Usage:

from hello_world import HelloWorld

hw = HelloWorld()
hw.send_string("Hello from Python!")
# Output: Swift received: Hello from Python!

Device Info Example (iOS)

Swift Code:

import UIKit
import PySwiftWrapper

@PyClass
class DeviceInfo {
    @PyInit
    init() {}
    
    @PyMethod
    func getDeviceName() -> String {
        return UIDevice.current.name
    }
    
    @PyMethod
    func getSystemVersion() -> String {
        return UIDevice.current.systemVersion
    }
    
    @PyMethod
    func getAllInfo() -> [String: String] {
        return [
            "name": UIDevice.current.name,
            "model": UIDevice.current.model,
            "system": UIDevice.current.systemName,
            "version": UIDevice.current.systemVersion
        ]
    }
}

@PyModule
struct DeviceInfoModule: PyModuleProtocol {
    static var py_classes: [any (PyClassProtocol & AnyObject).Type] = [
        DeviceInfo.self
    ]
}

Python Usage:

from device_info import DeviceInfo

device = DeviceInfo()

# Get individual properties
print(f"Device: {device.get_device_name()}")
print(f"iOS Version: {device.get_system_version()}")

# Get all information
info = device.get_all_info()
for key, value in info.items():
    print(f"{key}: {value}")

Callbacks from Swift to Python

Swift Code:

@PyClass
class HelloWorld {
    var _callback: PyPointer
    
    @PyInit
    init(callback: PyPointer) {
        _callback = callback
    }
    
    @PyMethod
    func sendString(text: String) {
        callback(text + " World")
    }
    
    @PyCall
    func callback(text: String)
}

Python Usage:

from hello_world import HelloWorld

def my_callback(text: str):
    print(f"Callback received: {text}")

hw = HelloWorld(my_callback)
hw.send_string("Hello")
# Output: Callback received: Hello World

# Or with lambda
hw = HelloWorld(lambda text: print(text))
hw.send_string("Hello")

πŸ”„ Type Conversions

PySwiftKit automatically converts between Python and Swift types:

Numeric Types

Python Type Swift Type Description
int Int, Int32, Int16, Int8 Signed integers
int UInt, UInt32, UInt16, UInt8 Unsigned integers
float Double, Float, Float16 Floating-point numbers

Collections

Python Type Swift Type Description
str String Unicode strings
bytes Data, [UInt8] Binary data
list[int] [Int], [UInt8] Integer arrays
list[float] [Double], [Float] Float arrays
list[str] [String] String arrays
dict [String: Any] Dictionaries

Example

@PyClass
class TypeConverter {
    @PyMethod
    func processInt(_ value: Int) {
        print("Received: \(value)")
    }
    
    @PyMethod
    func processFloats(_ values: [Double]) {
        print("Floats: \(values)")
    }
    
    @PyMethod
    func processData(_ data: Data) {
        print("Data size: \(data.count)")
    }
}
converter = TypeConverter()

converter.process_int(42)
converter.process_floats([3.14, 2.71, 1.41])
converter.process_data(b"Hello, Swift!")

πŸ“š Architecture

PySwiftKit uses a three-layer architecture:

  1. PySwiftKit - Low-level Python C API wrappers
  2. PySerializing - Type conversion protocols (PySerialize/PyDeserialize)
  3. PySwiftWrapper - Swift macros for automatic binding generation

GIL Management

PySwiftKit provides safe GIL (Global Interpreter Lock) management:

// Explicit GIL acquisition
withGIL {
    // Python C API calls here
}

// Conditional GIL acquisition
withAutoGIL {
    // Only acquires if not already held
}

// Check GIL state
if PyHasGIL() {
    // GIL is held
}

πŸ“– Documentation

🎯 Use Cases

  • iOS Apps with Python - Embed Python scripts in iOS applications
  • Data Science on Apple Platforms - Use Python data science libraries in Swift apps
  • Hybrid Applications - Combine Swift's performance with Python's ecosystem
  • Cross-Platform Tools - Share algorithmic code between Python and Swift
  • Rapid Prototyping - Prototype in Python, optimize in Swift

οΏ½οΏ½ Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

πŸ“„ License

PySwiftKit is released under the MIT License. See LICENSE for details.

πŸ”— Links


Made with ❀️ by the Py-Swift team

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors