Pass Swift Array To C++ As A std::vector

Hi --

I would like to be able to pass a Swift Array to C++ code. I know it should be possible, but having trouble figuring out the right way to do it. Here is an example class showing what I want to do.

C++ code:

class Foo {
public:
  Foo(const std::vector<uint8_t> & values) : _values(values) {}

protected:
  std::vector<uint_8> _values;
};

Swift code:

let values: [UInt8] = [ 1, 2, 3, 4, 5, 6 ]
var foo = Foo(values)

If I do this, I get the following error message: Cannot convert value of type '[UInt8]' to expected argument type 'std.__1.vector<UInt8, allocator<UInt8>>'.

I have looked at that link a few times and it does not solve my problem. It definitely would allow me to pass a std::vector from Swift into C++, but it is not the same as bridging between a Swift array and a C++ vector. Using this method would be much slower because it would require calling push_back multiple times while iterating through an array.

I did find a temporary workaround that at least got me going again. Instead of passing a std::vector in my C++ function, I switched to using a pointer and size parameter. I could then using an UnsafeRawPointer and the count to make the contents of the array available to the C++ code. From within C++, I created the std::vector. The downside is that this requires a memcpy, so this would not be ideal for large arrays.

I still would like to know if there is any bridging between Swift arrays and C++ std::vector (or std::array) that could be used for this case.

What exactly do you need to do with the data in each language?

Do you need to be able to modify the data from both sides? Or is it written by one side and read by the other?

Can you change the code on both sides? Or are you trying to bridge to existing code in one or other language that can't be modified?

Looking at your C++ code:

class Foo {
public:
  Foo(const std::vector<uint8_t> & values) : _values(values) {}

protected:
  std::vector<uint_8> _values;
};

You are, of course, copying from values into _values in the constructor. But you also have the option of writing the ctor like this:

  Foo(std::vector<uint8_t>&& values): _values(std::move(values)) {}

This will also copy in most cases, but unlike your version it elides the copy if the ctor is passed a temporary, i.e.

Foo make_foo();

void f()
{
  Foo fff( make_foo() );
}

I mention this because (a) it's good practice generally, but also (b) it will be easier to adapt a C++ API that uses value semantics to work with Swift than a C++ API that uses reference semantics.

In my current use case, I want to pass the data from Swift to C++ without any further modifications needing to be fed back into Swift. I can modify both sides of this code, and I have found a workaround that works for the moment. But I would like to avoid workarounds, especially when it seems like there should be some bridging for this use case.

In regards to move vs copy -- move would be ideal. But I didn't go further with this because of the first issue.

Pass Swift Array To C++ As A std::vector
 
 
Q