How to delete C++ class instance that uses SWIFT_UNSAFE_REFERENCE

I have a class that I've defined like this (as an example):

#include <swift/bridging>
#include <vector>

class MyClass {
public:
    MyClass () {}
    MyClass (const MyClass &) = delete; // non-copyable
    static MyClass *create() { return new MyClass(); }

    void addData(std::string str) { m_data.push_back(str); }
private:
    std::vector<std::string> m_data;
} SWIFT_UNSAFE_REFERENCE;

From the Swift side, I can create it and use it like this:

let myClass = MyClass.create()!
myClass.addData(std.string("My String"))

However, how do I then delete the myClass instance after I'm done using it? Is that possible with SWIFT_UNSAFE_REFERENCE?

You are allocating the class with a static C++ method: create. You should define a similar one destroy that deletes the class, and call that when you are done with myClass. If C++ constructs the class, we currently don't have any way to determine how it was allocated, so Swift cannot deallocate it for you. Further, SWIFT_UNSAFE_REFERENCE tells the compiler that you want to manage the class yourself, rather than letting Swift retain/release it. If you want the compiler to automatically destroy the class, you should use a SWIFT_SHARED_REFERENCE.

1 Like

Here you are using the new operator to allocate the class, but Swift doesn't know that. Short of some fairly complicated program analysis, Swift doesn't have any way to determine this. For example, maybe it was allocated with a custom arena allocator or something.

It might be nice for Swift to provide default allocators for foreign reference types, or try to identify common patterns such as the new operator being used in a static factory method, but as far as I know, that is not implemented right now.

Okay so it works! Just adding a destroy method seems to do the job :)

class MyClass {
public:
    MyClass () {}
    MyClass (const MyClass &) = delete; // non-copyable
    static MyClass *create() { return new MyClass(); }
    static void destroy(MyClass *obj) { delete obj; }

    void addData(std::string str) { m_data.push_back(str); }
private:
    std::vector<std::string> m_data;
} SWIFT_UNSAFE_REFERENCE;

Then I do a MyClass.destroy(myClass) when I want it to be gone, and all is good!

Thanks!