What is the suggested way to pass array/vector data back and forth from swift and cpp?

You can convert a swift::Array to a std::vector using the following explicit constructor of std::vector:

auto cxxVector = std::vector<int>(intArray.begin(), intArray.end());
This constructor copies over the elements from the Swift array into the constructed C++ vector.

You can also convert a vector to a swift::Array using the following explicit constructor of swift::Array:

auto swiftIntArray = swift::Array<int>(cxxVector);
This constructor copies over the elements from the C++ vector into the constructed Swift array.

I have a type in cpp that takes a vector.I am not able to figure out how to construct this vector instance from swift.

It seems that in cpp there is an easy way to convert back and forth for these, I am guessing that this suggests that I should add a contractor that takes a swift array.

I would like to take a swift array and convert it to a vector that I can just pass in to the constructor.

This is how the std::vector init looks like in swift

let someInstance = scad.KeyGrid.init(data: std.__1.vector<vector<UnsafeMutablePointer<Key>, allocator<UnsafeMutablePointer<Key>>>, allocator<vector<UnsafeMutablePointer<Key>, allocator<UnsafeMutablePointer<Key>>>>>)

C++ templates cannot be instantiated from Swift code, AIUI. I believe you have to typedef std::vector<...> MyVector; or using MyVector = std::vector<...>; in C++ somewhere, and then use the MyVector alias in Swift.

// cpp side

using KeyVector = std::vector<Key*>;



// swift side

func convert (_ inputArray: [scad.Key]) -> scad.KeyVector {
    var tempResult = scad.KeyVector()
    tempResult.reserve(inputArray.count)
    for item in inputArray {
        tempResult.push_back(item) // cannot convert value of type 'scad.Key' to expected argument type 'std.__1.vector<UnsafeMutablePointer<Key>, allocator<UnsafeMutablePointer<Key>>>.value_type?' (aka 'Optional<UnsafeMutablePointer<scad.Key>>')sourcek
    }
    return tempResult
}

cc @egor.zhdan

Using a vector of UnsafeMutablePointers from Swift is usually not a good idea, because it's quite tricky to do it in a memory-safe way. I would recommend using a std::vector<Key> if possible, then you will be able to simply use scad.KeyVector(inputArray) to convert a Swift array to a vector. Would this be viable for your use case?

Ah I see. The issue is the Key as pointer which doest bridge nicely.

Would it be seamless if I update all those pointers to be std::Optional?

Yes, mostly! Switching to std::optional would let you construct an element of the vector from Swift while preserving memory safety:

// C++
using OptionalKey = std::optional<Key>;
// Swift
for item in inputArray {
    var opt = OptionalKey()
    opt.pointee = item
    tempResult.push_back(opt)
}
1 Like

Creating vector via push_back is by far the most time consuming operation in my code!

Is there another method by copying memory or (ideally) by using the same memory?