{"id":28435193,"url":"https://github.com/skiptools/skip-integ-demo","last_synced_at":"2025-07-12T06:33:27.203Z","repository":{"id":264565379,"uuid":"893698215","full_name":"skiptools/skip-integ-demo","owner":"skiptools","description":"Demonstration of a simple Swift-Kotlin bridged model using SkipFuse","archived":false,"fork":false,"pushed_at":"2025-07-10T19:21:14.000Z","size":33,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-07-11T05:00:54.550Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://skip.tools/docs/modes/","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skiptools.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-11-25T03:37:49.000Z","updated_at":"2025-07-10T19:21:18.000Z","dependencies_parsed_at":"2025-02-23T11:24:13.003Z","dependency_job_id":"b49784d1-17df-4f2f-9695-4c1ba42ed243","html_url":"https://github.com/skiptools/skip-integ-demo","commit_stats":null,"previous_names":["skiptools/skip-integ-demo"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/skiptools/skip-integ-demo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skiptools%2Fskip-integ-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skiptools%2Fskip-integ-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skiptools%2Fskip-integ-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skiptools%2Fskip-integ-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skiptools","download_url":"https://codeload.github.com/skiptools/skip-integ-demo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skiptools%2Fskip-integ-demo/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264951610,"owners_count":23687974,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-05T20:06:53.713Z","updated_at":"2025-07-12T06:33:27.195Z","avatar_url":"https://github.com/skiptools.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Skip Native Integration Demo\n\nThis project demonstrates bridging between Swift and Kotlin \nusing the [SkipFuse](https://skip.tools/docs/modules/skip-fuse/) framework,\nas part of Skip's [native](https://skip.tools/docs/modes/) mode.\n\nIt is meant as a showcase of how bridging is generated and\nused, both at build time and runtime.\n\n\u003e [!WARNING]  \n\u003e These internal details about how bridging is generated are subject to change between SkipFuse releases, so you should not rely on any specific signatures, either on the Swift/C side or on the Kotlin/Java side.\n\n## Examples\n\n### Function\n\n#### Swift\n\n```swift\npublic func stringFunction() -\u003e String {\n    \"Hello, World!\"\n}\n```\n\n#### Kotlin\n\n```kotlin\nfun stringFunction(): String = Swift_stringFunction_0()\n\nprivate external fun Swift_stringFunction_0(): String\n```\n\n#### Bridged Swift\n\n```swift\n@_cdecl(\"Java_skip_integ_demo_SkipIntegDemoKt_Swift_1stringFunction_10\")\nfunc SkipIntegDemoKt_Swift_stringFunction_0(_ Java_env: JNIEnvPointer, _ Java_target: JavaObjectPointer) -\u003e JavaString {\n    let f_return_swift = stringFunction()\n    return f_return_swift.toJavaObject(options: [.kotlincompat])!\n}\n```\n\n\n### Async Function\n\n#### Swift\n\n```swift\npublic func stringFunctionAsync() async throws -\u003e String {\n    \"Hello, World!\"\n}\n```\n\n#### Kotlin\n\n```kotlin\nsuspend fun stringFunctionAsync(): String = Async.run {\n    kotlin.coroutines.suspendCoroutine { f_continuation -\u003e\n        Swift_callback_stringFunctionAsync_1() { f_return, f_error -\u003e\n            if (f_error != null) {\n                f_continuation.resumeWith(kotlin.Result.failure(f_error))\n            } else {\n                f_continuation.resumeWith(kotlin.Result.success(f_return!!))\n            }\n        }\n    }\n}\n\nprivate external fun Swift_callback_stringFunctionAsync_1(f_callback: (String?, Throwable?) -\u003e Unit)\n```\n\n#### Bridged Swift\n\n```swift\n@_cdecl(\"Java_skip_integ_demo_SkipIntegDemoKt_Swift_1callback_1stringFunctionAsync_11\")\nfunc SkipIntegDemoKt_Swift_callback_stringFunctionAsync_1(_ Java_env: JNIEnvPointer, _ Java_target: JavaObjectPointer, _ f_callback: JavaObjectPointer) {\n    let f_callback_swift = SwiftClosure2.closure(forJavaObject: f_callback, options: [.kotlincompat])! as (String?, JavaObjectPointer?) -\u003e Void\n    Task {\n        do {\n            let f_return_swift = try await stringFunctionAsync()\n            f_callback_swift(f_return_swift, nil)\n        } catch {\n            jniContext {\n                f_callback_swift(nil, JThrowable.toThrowable(error, options: [.kotlincompat])!)\n            }\n        }\n    }\n}\n```\n\n### Throwing Function with Custom Error\n\n#### Swift\n\n```swift\npublic func throwingFunction() throws {\n    throw CustomError.err\n}\n\npublic enum CustomError : Error {\n    case err\n}\n```\n\n#### Kotlin\n\n```kotlin\nfun throwingFunction(): Unit = Swift_throwingFunction_2()\n\nprivate external fun Swift_throwingFunction_2()\n\nsealed class CustomError: Exception(), Error, skip.lib.SwiftProjecting {\n\n    class ErrCase: CustomError() {\n        override fun equals(other: Any?): Boolean = other is ErrCase\n        override fun hashCode(): Int = \"ErrCase\".hashCode()\n    }\n\n    override fun Swift_projection(options: Int): () -\u003e Any = Swift_projectionImpl(options)\n    private external fun Swift_projectionImpl(options: Int): () -\u003e Any\n\n    companion object {\n        val err: CustomError\n            get() = ErrCase()\n    }\n}\n```\n\n#### Bridged Swift\n\n```swift\n@_cdecl(\"Java_skip_integ_demo_SkipIntegDemoKt_Swift_1throwingFunction_12\")\nfunc SkipIntegDemoKt_Swift_throwingFunction_2(_ Java_env: JNIEnvPointer, _ Java_target: JavaObjectPointer) {\n    do {\n        try throwingFunction()\n    } catch {\n        JThrowable.throw(error, options: [.kotlincompat], env: Java_env)\n    }\n}\n\n@_cdecl(\"Java_skip_integ_demo_CustomError_Swift_1projectionImpl\")\nfunc CustomError_Swift_projectionImpl(_ Java_env: JNIEnvPointer, _ Java_target: JavaObjectPointer, _ options: Int32) -\u003e JavaObjectPointer {\n    let projection = CustomError.fromJavaObject(Java_target, options: JConvertibleOptions(rawValue: Int(options)))\n    let factory: () -\u003e Any = { projection }\n    return SwiftClosure0.javaObject(for: factory, options: [.kotlincompat])!\n}\n\nextension CustomError: BridgedToKotlin {\n    private static let Java_class = try! JClass(name: \"skip/integ/demo/CustomError\")\n    private static let Java_Companion_class = try! JClass(name: \"skip/integ/demo/CustomError$Companion\")\n    private static let Java_Companion = JObject(Java_class.getStatic(field: Java_class.getStaticFieldID(name: \"Companion\", sig: \"Lskip/integ/demo/CustomError$Companion;\")!, options: [.kotlincompat]))\n    public static func fromJavaObject(_ obj: JavaObjectPointer?, options: JConvertibleOptions) -\u003e Self {\n        let className = Java_className(of: obj!, options: options)\n        return fromJavaClassName(className, obj!, options: options)\n    }\n    fileprivate static func fromJavaClassName(_ className: String, _ obj: JavaObjectPointer, options: JConvertibleOptions) -\u003e Self {\n        switch className {\n        case \"skip.integ.demo.CustomError$ErrCase\":\n            return .err\n        default: fatalError()\n        }\n    }\n    public func toJavaObject(options: JConvertibleOptions) -\u003e JavaObjectPointer? {\n        switch self {\n        case .err:\n            return try! Self.Java_Companion.call(method: Self.Java_Companion_err_methodID, options: options, args: [])\n        }\n    }\n    private static let Java_Companion_err_methodID = Java_Companion_class.getMethodID(name: \"getErr\", sig: \"()Lskip/integ/demo/CustomError;\")!\n}\n```\n\n### Class\n\n#### Swift\n\n```swift\npublic class SkipIntegDemoModule {\n    public init() {\n    }\n}\n```\n\n#### Kotlin\n\n```kotlin\nopen class SkipIntegDemoModule: skip.bridge.kt.SwiftPeerBridged, skip.lib.SwiftProjecting {\n    var Swift_peer: skip.bridge.kt.SwiftObjectPointer = skip.bridge.kt.SwiftObjectNil\n\n    constructor(Swift_peer: skip.bridge.kt.SwiftObjectPointer, marker: skip.bridge.kt.SwiftPeerMarker?) {\n        this.Swift_peer = Swift_peer\n    }\n\n    fun finalize() {\n        Swift_release(Swift_peer)\n        Swift_peer = skip.bridge.kt.SwiftObjectNil\n    }\n    private external fun Swift_release(Swift_peer: skip.bridge.kt.SwiftObjectPointer)\n\n    override fun Swift_peer(): skip.bridge.kt.SwiftObjectPointer = Swift_peer\n\n    override fun equals(other: Any?): Boolean {\n        if (other !is skip.bridge.kt.SwiftPeerBridged) return false\n        return Swift_peer == other.Swift_peer()\n    }\n\n    override fun hashCode(): Int = Swift_peer.hashCode()\n\n    constructor() {\n        Swift_peer = Swift_constructor_0()\n    }\n    private external fun Swift_constructor_0(): skip.bridge.kt.SwiftObjectPointer\n\n    override fun Swift_projection(options: Int): () -\u003e Any = Swift_projectionImpl(options)\n    private external fun Swift_projectionImpl(options: Int): () -\u003e Any\n\n    companion object: CompanionClass() {\n    }\n    open class CompanionClass {\n    }\n}\n```\n\n#### Bridged Swift\n\n```swift\n@_cdecl(\"Java_skip_integ_demo_SkipIntegDemoModule_Swift_1release\")\nfunc SkipIntegDemoModule_Swift_release(_ Java_env: JNIEnvPointer, _ Java_target: JavaObjectPointer, _ Swift_peer: SwiftObjectPointer) {\n    Swift_peer.release(as: SkipIntegDemoModule.self)\n}\n\n@_cdecl(\"Java_skip_integ_demo_SkipIntegDemoModule_Swift_1constructor_10\")\nfunc SkipIntegDemoModule_Swift_constructor_0(_ Java_env: JNIEnvPointer, _ Java_target: JavaObjectPointer) -\u003e SwiftObjectPointer {\n    let f_return_swift = SkipIntegDemoModule()\n    return SwiftObjectPointer.pointer(to: f_return_swift, retain: true)\n}\n\n@_cdecl(\"Java_skip_integ_demo_SkipIntegDemoModule_Swift_1projectionImpl\")\nfunc SkipIntegDemoModule_Swift_projectionImpl(_ Java_env: JNIEnvPointer, _ Java_target: JavaObjectPointer, _ options: Int32) -\u003e JavaObjectPointer {\n    let projection = SkipIntegDemoModule.fromJavaObject(Java_target, options: JConvertibleOptions(rawValue: Int(options)))\n    let factory: () -\u003e Any = { projection }\n    return SwiftClosure0.javaObject(for: factory, options: [.kotlincompat])!\n}\n\nextension SkipIntegDemoModule: BridgedToKotlin, BridgedToKotlinBaseClass {\n    private static let Java_class = try! JClass(name: \"skip/integ/demo/SkipIntegDemoModule\")\n    public static func fromJavaObject(_ obj: JavaObjectPointer?, options: JConvertibleOptions) -\u003e Self {\n        let ptr = SwiftObjectPointer.peer(of: obj!, options: options)\n        return ptr.pointee()!\n    }\n    public func toJavaObject(options: JConvertibleOptions) -\u003e JavaObjectPointer? {\n        let Swift_peer = SwiftObjectPointer.pointer(to: self, retain: true)\n        let constructor = Java_findConstructor(base: Self.Java_class, Self.Java_constructor_methodID)\n        return try! constructor.cls.create(ctor: constructor.ctor, options: options, args: [Swift_peer.toJavaParameter(options: options), (nil as JavaObjectPointer?).toJavaParameter(options: options)])\n    }\n    private static let Java_constructor_methodID = Java_class.getMethodID(name: \"\u003cinit\u003e\", sig: \"(JLskip/bridge/kt/SwiftPeerMarker;)V\")!\n}\n```\n\n### Equatable Struct\n\n#### Swift\n\n```swift\npublic struct EquatableStruct : Equatable {\n    public var string: String\n\n    public init(string: String) {\n        self.string = string\n    }\n}\n```\n\n#### Kotlin\n\n```kotlin\nclass EquatableStruct: MutableStruct, skip.bridge.kt.SwiftPeerBridged, skip.lib.SwiftProjecting {\n    var Swift_peer: skip.bridge.kt.SwiftObjectPointer = skip.bridge.kt.SwiftObjectNil\n\n    constructor(Swift_peer: skip.bridge.kt.SwiftObjectPointer, marker: skip.bridge.kt.SwiftPeerMarker?) {\n        this.Swift_peer = Swift_peer\n    }\n\n    fun finalize() {\n        Swift_release(Swift_peer)\n        Swift_peer = skip.bridge.kt.SwiftObjectNil\n    }\n    private external fun Swift_release(Swift_peer: skip.bridge.kt.SwiftObjectPointer)\n\n    override fun Swift_peer(): skip.bridge.kt.SwiftObjectPointer = Swift_peer\n\n    override fun hashCode(): Int = Swift_peer.hashCode()\n\n    var string: String\n        get() = Swift_string(Swift_peer)\n        set(newValue) {\n            willmutate()\n            try {\n                Swift_string_set(Swift_peer, newValue)\n            } finally {\n                didmutate()\n            }\n        }\n    private external fun Swift_string(Swift_peer: skip.bridge.kt.SwiftObjectPointer): String\n    private external fun Swift_string_set(Swift_peer: skip.bridge.kt.SwiftObjectPointer, value: String)\n    constructor(string: String) {\n        Swift_peer = Swift_constructor_0(string)\n    }\n    private external fun Swift_constructor_0(string: String): skip.bridge.kt.SwiftObjectPointer\n    private constructor(copy: skip.lib.MutableStruct) {\n        Swift_peer = Swift_constructor_1(copy)\n    }\n    private external fun Swift_constructor_1(copy: skip.lib.MutableStruct): skip.bridge.kt.SwiftObjectPointer\n\n    override var supdate: ((Any) -\u003e Unit)? = null\n    override var smutatingcount = 0\n    override fun scopy(): MutableStruct = EquatableStruct(this as MutableStruct)\n    override fun equals(other: Any?): Boolean {\n        if (other === this) return true\n        if (other !is EquatableStruct) return false\n        return Swift_isequal(this, other)\n    }\n    private external fun Swift_isequal(lhs: EquatableStruct, rhs: EquatableStruct): Boolean\n\n    override fun Swift_projection(options: Int): () -\u003e Any = Swift_projectionImpl(options)\n    private external fun Swift_projectionImpl(options: Int): () -\u003e Any\n\n    companion object {\n    }\n}\n```\n\n#### Bridged Swift\n\n```swift\n@_cdecl(\"Java_skip_integ_demo_EquatableStruct_Swift_1release\")\nfunc EquatableStruct_Swift_release(_ Java_env: JNIEnvPointer, _ Java_target: JavaObjectPointer, _ Swift_peer: SwiftObjectPointer) {\n    Swift_peer.release(as: SwiftValueTypeBox\u003cEquatableStruct\u003e.self)\n}\n\n@_cdecl(\"Java_skip_integ_demo_EquatableStruct_Swift_1string\")\nfunc EquatableStruct_Swift_string(_ Java_env: JNIEnvPointer, _ Java_target: JavaObjectPointer, _ Swift_peer: SwiftObjectPointer) -\u003e JavaString {\n    let peer_swift: SwiftValueTypeBox\u003cEquatableStruct\u003e = Swift_peer.pointee()!\n    return peer_swift.value.string.toJavaObject(options: [.kotlincompat])!\n}\n\n@_cdecl(\"Java_skip_integ_demo_EquatableStruct_Swift_1string_1set\")\nfunc EquatableStruct_Swift_string_set(_ Java_env: JNIEnvPointer, _ Java_target: JavaObjectPointer, _ Swift_peer: SwiftObjectPointer, _ value: JavaString) {\n    let peer_swift: SwiftValueTypeBox\u003cEquatableStruct\u003e = Swift_peer.pointee()!\n    peer_swift.value.string = String.fromJavaObject(value, options: [.kotlincompat])\n}\n\n@_cdecl(\"Java_skip_integ_demo_EquatableStruct_Swift_1constructor_10\")\nfunc EquatableStruct_Swift_constructor_0(_ Java_env: JNIEnvPointer, _ Java_target: JavaObjectPointer, _ p_0: JavaString) -\u003e SwiftObjectPointer {\n    let p_0_swift = String.fromJavaObject(p_0, options: [.kotlincompat])\n    let f_return_swift = SwiftValueTypeBox(EquatableStruct(string: p_0_swift))\n    return SwiftObjectPointer.pointer(to: f_return_swift, retain: true)\n}\n\n@_cdecl(\"Java_skip_integ_demo_EquatableStruct_Swift_1constructor_11\")\nfunc EquatableStruct_Swift_constructor_1(_ Java_env: JNIEnvPointer, _ Java_target: JavaObjectPointer, _ p_0: JavaObjectPointer) -\u003e SwiftObjectPointer {\n    let p_0_swift = EquatableStruct.fromJavaObject(p_0, options: [.kotlincompat])\n    let f_return_swift = SwiftValueTypeBox(p_0_swift)\n    return SwiftObjectPointer.pointer(to: f_return_swift, retain: true)\n}\n\n@_cdecl(\"Java_skip_integ_demo_EquatableStruct_Swift_1isequal\")\nfunc EquatableStruct_Swift_isequal(_ Java_env: JNIEnvPointer, _ Java_target: JavaObjectPointer, _ lhs: JavaObjectPointer, _ rhs: JavaObjectPointer) -\u003e Bool {\n    let lhs_swift = EquatableStruct.fromJavaObject(lhs, options: [.kotlincompat])\n    let rhs_swift = EquatableStruct.fromJavaObject(rhs, options: [.kotlincompat])\n    return lhs_swift == rhs_swift\n}\n\n@_cdecl(\"Java_skip_integ_demo_EquatableStruct_Swift_1projectionImpl\")\nfunc EquatableStruct_Swift_projectionImpl(_ Java_env: JNIEnvPointer, _ Java_target: JavaObjectPointer, _ options: Int32) -\u003e JavaObjectPointer {\n    let projection = EquatableStruct.fromJavaObject(Java_target, options: JConvertibleOptions(rawValue: Int(options)))\n    let factory: () -\u003e Any = { projection }\n    return SwiftClosure0.javaObject(for: factory, options: [.kotlincompat])!\n}\n\nextension EquatableStruct: BridgedToKotlin {\n    private static let Java_class = try! JClass(name: \"skip/integ/demo/EquatableStruct\")\n    public static func fromJavaObject(_ obj: JavaObjectPointer?, options: JConvertibleOptions) -\u003e Self {\n        let ptr = SwiftObjectPointer.peer(of: obj!, options: options)\n        let box: SwiftValueTypeBox\u003cSelf\u003e = ptr.pointee()!\n        return box.value\n    }\n    public func toJavaObject(options: JConvertibleOptions) -\u003e JavaObjectPointer? {\n        let box = SwiftValueTypeBox(self)\n        let Swift_peer = SwiftObjectPointer.pointer(to: box, retain: true)\n        return try! Self.Java_class.create(ctor: Self.Java_constructor_methodID, options: options, args: [Swift_peer.toJavaParameter(options: options), (nil as JavaObjectPointer?).toJavaParameter(options: options)])\n    }\n    private static let Java_constructor_methodID = Java_class.getMethodID(name: \"\u003cinit\u003e\", sig: \"(JLskip/bridge/kt/SwiftPeerMarker;)V\")!\n}\n```\n\n\n## Building\n\nThis project is a Swift Package Manager module that uses the\n[Skip](https://skip.tools) plugin to transpile Swift into Kotlin.\n\nBuilding the module requires that Skip be installed using \n[Homebrew](https://brew.sh) with `brew install skiptools/skip/skip`.\nThis will also install the necessary build prerequisites:\nKotlin, Gradle, and the Android build tools.\n\n## Testing\n\nThe module can be tested using the standard `swift test` command\nor by running the test target for the macOS destination in Xcode,\nwhich will run the Swift tests as well as the transpiled\nKotlin JUnit tests in the Robolectric Android simulation environment.\n\nParity testing can be performed with `skip test`,\nwhich will output a table of the test results for both platforms.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskiptools%2Fskip-integ-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskiptools%2Fskip-integ-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskiptools%2Fskip-integ-demo/lists"}