heremaps / gluecodium

Cross-language bindings generator for C++, Java, Swift, and Dart
Apache License 2.0
202 stars 27 forks source link

Duplicate cbridge converting functions for a derived class for cross framework workflow #1312

Closed Hsilgos closed 2 years ago

Hsilgos commented 2 years ago

When interface is declared in one framework A in lime file and derived in different framework B it leads to compilation error because generated derived class in Swift is trying to use cbridge functions for interface (which are in framework A). Test which represent the issue is here: https://github.com/heremaps/gluecodium/pull/1311 Gluecodum generates protocol CommonMainBase in framework ModuleWithMainAndCommon:

public protocol CommonMainBase : AnyObject {
    var commonBaseId: Int64 { get set }
    var commonBaseEnum: CommonBaseEnum { get set }
    var commonBaseTypeFoo: CommonMainFoo { get set }
    func getBaseId() -> Int64
    func setBaseId(value: Int64) -> Void
    func getBaseEnum() -> CommonBaseEnum
    func setBaseEnum(value: CommonBaseEnum) -> Void
    func getBaseTypeFoo() -> CommonMainFoo
    func setBaseTypeFoo(value: CommonMainFoo) -> Void
}

and class MainDerived in other dependant framework ObjectWithMainOnly:

public class MainDerived: CommonMainBase {

    public var commonBaseId: Int64 {
        get {
            let c_result_handle = unit_test_CommonMainBase_commonBaseId_get(self.c_instance)
            return moveFromCType(c_result_handle)
        }
        set {
            let c_value = moveToCType(newValue)
            unit_test_CommonMainBase_commonBaseId_set(self.c_instance, c_value.ref)
        }
    }
    public var commonBaseEnum: CommonBaseEnum {
        get {
            let c_result_handle = unit_test_CommonMainBase_commonBaseEnum_get(self.c_instance)
            return moveFromCType(c_result_handle)
        }
        set {
            let c_value = moveToCType(newValue)
            unit_test_CommonMainBase_commonBaseEnum_set(self.c_instance, c_value.ref)
        }
    }
    public var commonBaseTypeFoo: CommonMainFoo {
        get {
            let c_result_handle = unit_test_CommonMainBase_commonBaseTypeFoo_get(self.c_instance)
            return CommonMainFoo_moveFromCType(c_result_handle)
        }
        set {
            let c_value = moveToCType(newValue)
            unit_test_CommonMainBase_commonBaseTypeFoo_set(self.c_instance, c_value.ref)
        }
    }
    public var id: Int64 {
        get {
            let c_result_handle = unit_test_MainDerived_id_get(self.c_instance)
            return moveFromCType(c_result_handle)
        }
    }
    let c_instance : _baseRef

    init(cMainDerived: _baseRef) {
        guard cMainDerived != 0 else {
            fatalError("Nullptr value is not supported for initializers")
        }
        c_instance = cMainDerived
    }

    deinit {
        unit_test_MainDerived_remove_swift_object_from_wrapper_cache(c_instance)
        unit_test_MainDerived_release_handle(c_instance)
    }

    public func getBaseId() -> Int64 {
        let c_result_handle = unit_test_CommonMainBase_getBaseId(self.c_instance)
        return moveFromCType(c_result_handle)
    }
    public func setBaseId(value: Int64) -> Void {
        let c_value = moveToCType(value)
        unit_test_CommonMainBase_setBaseId(self.c_instance, c_value.ref)
    }
    public func getBaseEnum() -> CommonBaseEnum {
        let c_result_handle = unit_test_CommonMainBase_getBaseEnum(self.c_instance)
        return moveFromCType(c_result_handle)
    }
    public func setBaseEnum(value: CommonBaseEnum) -> Void {
        let c_value = moveToCType(value)
        unit_test_CommonMainBase_setBaseEnum(self.c_instance, c_value.ref)
    }
    public func getBaseTypeFoo() -> CommonMainFoo {
        let c_result_handle = unit_test_CommonMainBase_getBaseTypeFoo(self.c_instance)
        return CommonMainFoo_moveFromCType(c_result_handle)
    }
    public func setBaseTypeFoo(value: CommonMainFoo) -> Void {
        let c_value = moveToCType(value)
        unit_test_CommonMainBase_setBaseTypeFoo(self.c_instance, c_value.ref)
    }

}

So derived class uses cbridge functions prefixed with unit_test_CommonMainBase_ which are in framework ModuleWithMainAndCommon and not accessible.

Since each such function is lightweight the easiest solution is to duplicate such functions for each derived class.

DanielKamkha commented 2 years ago

Also affects Dart. Does not affect Java or C++.

DanielKamkha commented 2 years ago

Fails to compile with the internal Dart build. If the parent interface contains overloaded functions, the "new" code fails to properly disambiguate those in FFI. Probably affects Swift/CBridge in the same way.