Skip to content

[cxx-interop, maccatalyst] String and std::string conversion does not work on Mac Catalyst as it does on iOS, macOS and Linux #77000

Open
@wmanth

Description

@wmanth

Description

Working on a Swift package using C++ interoperability I am facing an issue handling string conversion between Swift String and C++ std::string.

My C++ proxy class with exception handling looks like this:

struct CxxError {
private:
    int _code;
    std::string _message;

public:
    int getCode() const SWIFT_COMPUTED_PROPERTY { return _code; }
    std::string getMessage() const SWIFT_COMPUTED_PROPERTY { return _message; }

    CxxError() : _code(0), _message(std::string()) {}
    CxxError(const Error& error) : _code(error.code()), _message(error.what()) {}
};

#pragma mark -

class CxxProxy {
public:
    CxxProxy(const std::string& name, Error& error);
}

Accordingly a Swift wrapper class handling errors with Swift exceptions looks like:

public class SwiftWrapper {
    public let url: URL
    private var cxxProxy: CxxProxy

    struct Error: Swift.Error {
        let message: String

        init(message: std.string) {
            self.message = String(message)
        }
    }

    public init(url: URL) throws {
        var error = CxxError()
        let cxxProxy = CxxProxy(std.string(url.path), &error)

        guard error.code == 0 else {
            throw Error(message: error.message)
        }

        self.url = url
        self.cxxProxy = cxxProxy
    }

While targeting iOS, macOS and Linux this code compiles and runs without any issues, on MacCatalyst the compiler reports two string conversion related issues:

error: no exact matches in call to initializer 
            self.message = String(message)
                           ^
Swift.String:4:23: note: candidate requires that 'std.string' (aka 'std.__1.basic_string<CChar, char_traits<CChar>, allocator<CChar>>') conform to 'LosslessStringConvertible' (requirement specified as 'T' : 'LosslessStringConvertible')
    @inlinable public init<T>(_ value: T) where T : LosslessStringConvertible
                      ^
Swift.String:2:12: note: candidate requires that 'std.string' (aka 'std.__1.basic_string<CChar, char_traits<CChar>, allocator<CChar>>') conform to 'BinaryInteger' (requirement specified as 'T' : 'BinaryInteger')
    public init<T>(_ value: T, radix: Int = 10, uppercase: Bool = false) where T : BinaryInteger
           ^
Swift.String:4:12: note: candidate requires that 'std.string' (aka 'std.__1.basic_string<CChar, char_traits<CChar>, allocator<CChar>>') conform to 'Sequence' (requirement specified as 'S' : 'Sequence')
    public init<S>(_ characters: S) where S : Sequence, S.Element == Character
           ^
Swift.RangeReplaceableCollection:3:23: note: candidate requires that 'std.string' (aka 'std.__1.basic_string<CChar, char_traits<CChar>, allocator<CChar>>') conform to 'Sequence' (requirement specified as 'S' : 'Sequence')
    @inlinable public init<S>(_ elements: S) where S : Sequence, Self.Element == S.Element
                      ^
Swift.String:2:12: note: incorrect labels for candidate (have: '(_:)', expected: '(describing:)')
    public init<Subject>(describing instance: Subject)
           ^
Swift.String:6:12: note: incorrect labels for candidate (have: '(_:)', expected: '(reflecting:)')
    public init<Subject>(reflecting subject: Subject)
           ^
error: no exact matches in call to initializer 
        let imageProxy = CxxProxy(std.string(url.path), &error)
                                    ^
__ObjC.std:1155:20: note: candidate expects value of type 'std.__1.basic_string<CChar, char_traits<CChar>, allocator<CChar>>.allocator_type' (aka 'std.__1.allocator<CChar>') for parameter #1 (got 'String')
            public init(_ __a: std.__1.basic_string<CChar, char_traits<CChar>, allocator<CChar>>.allocator_type)
                   ^
__ObjC.std:1162:20: note: candidate expects value of type 'std.initializer_list<CChar>' for parameter #1 (got 'String')
            public init(_ __il: std.initializer_list<CChar>)
                   ^

Reproduction

Use above code to reproduce in a sample project.

Alternatively use my original SwiftExiv2 package to compile in Xcode with Mac Catalyst as target.

Expected behavior

Mac Catalyst should compile above code the same way successfully as it does with iOS, macOS and Linux as target.

Environment

Swift: swift-driver version: 1.115 Apple Swift version 6.0 (swiftlang-6.0.0.9.10 clang-1600.0.26.2) Target: arm64-apple-macosx15.0
Xcode: Xcode 16.0 Build version 16A242d
Deployment target: Mac Catalyst

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    CxxArea → standard library: The `Cxx` moduleMac CatalystPlatform: Mac CatalystbugA deviation from expected or documented behavior. Also: expected but undesirable behavior.c++ to swiftFeature → c++ interop: c++ to swiftswift 6.0unexpected errorBug: Unexpected error

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions