How to call method for C++ non-Copyable type

Swift with C++: Calling Methods on Non-Copyable C++ Class from Swift

Hello everyone,

I'm working on integrating a C++ class with Swift and have encountered an issue with method accessibility after making the C++ class(struct in Swift) non-copyable. I'd appreciate any guidance on resolving this.

Current Setup

I have a C++ class Server that manages a unique resource:

class Server {
public:
    Server(ServerMode mode);
    CFURLRef _Nullable copy_url() const;
    void shutdown();
    
private:
    int32_t sockfd;  // Unique resource
};

The Issue

Initially, I used let server = Server(mode: xx) and could successfully call copy_url(). However, when I needed to call shutdown(), I had to change it to var which caused issues due to sockfd being a unique resource.

To address this, I made the Server class non-copyable by deleting the copy constructor and copy assignment operator.

class Server {
public:
    Server(ServerMode mode);
    CFURLRef _Nullable copy_url() const;
    void shutdown();
    
    // Made non-copyable
    Server(Server&& other);
    Server& operator=(Server&& other);
    Server(const Server&) = delete;
    Server& operator=(const Server&) = delete;
    
private:
    int32_t sockfd;  // Unique resource
};

While this resolved the resource management issue and allows me to use var with shutdown(), I can no longer call copy_url().

The error I'm receiving is:

Value of type 'Server' has no member 'copy_url'

Question

Is there a way to call methods on a non-copyable value in C++ from Swift? I suspect the issue is that calling copy_url() might be attempting to make a copy, which is now forbidden.

Any suggestions on how to maintain both the non-copyable semantics and method accessibility would be greatly appreciated.

Thank you for your time and assistance!

Try annotating it as SWIFT_UNSAFE_REFERENCE from <swift/bridging>. You may have to add static create and destroy methods that wrap the constructor and destructor to call them from Swift.

1 Like

Making it a reference representation in Swift can certainly solve the issue.

But I'm still wondering why I can't call non-mutating function to a non Copyable struct in Swift if the type is from a C++ class.

Maybe this is a known issue which will be support later or maybe I'm missing some attribute keywords to the copy_url function signature? (eg. consuming / borrowing)

Found the solution:

After making Server as a non Copyable type, other const function can still be called directly.

And only copy_url will become __copy_urlUnsafe in Swift. See explanation here Swift.org - Mixing Swift and C++. (Thanks @crystdragon for pointing out this to me)

Since we know we are actually make a copy of CFURL internally via CFURLCreateWithBytes, I then solve it by adding the following code.

#include <swift/bridging>

...
    CFURLRef _Nullable copy_url() const SWIFT_RETURNS_INDEPENDENT_VALUE;
...
2 Likes