views:

32

answers:

1

How's that for a catchy title?

I need to convert back and forth from a CLR compliant type, like an array, and a std::vector type.

Are there any adapter methods out there, or should I just keep copying it in and out each time I call one of my native methods?

There are some interesting methods for converting between the cliext STL variant classes and CLR types, but I'm at a loss for how to get the standard vector into the STL types without a for next loop.

This is what I'm doing all over the place in this project:

vector<double> galilVector = _galilClass->arrayUpload(marshal_as<string>(arrayName));
List<double>^ arrayList = gcnew List<double>();

// Copy out the vector into a list for export to .net
for(vector<double>::size_type i = 0; i < galilVector.size(); i++) 
{
    arrayList->Add(galilVector[i]);
}

return arrayList->ToArray();
A: 

Instead of "doing that all over the place", why don't you make that logic into a reusable function?

Something like

template<typename T>
generic<typename S>
std::vector<T> marshal_as(System::Collections::Generic::ICollection<S>^ list)
{
  if (list == nullptr) throw gcnew ArgumentNullException(L"list");
  std::vector<T> result;
  result.reserve(list->Count);
  for each (S& elem in list)
    result.push_back(marshal_as<T>(elem));
  return result;
}

Remember to use vector's swap member function to quickly move the elements into the vector you want to hold them, if you just assign then a zillion copy constructors would be called.

Ben Voigt
Thanks. That is a good reusable solution.
Scott P
Can you elaborate on the swap reference above? I don't use STL much.
Scott P
The assignment operator and copy constructor for `std::vector` both do a deep copy. So `std::vector<string> xyz = marshal_as<string>(SomeCollectionOfSystemString);` will convert all the .NET string into C++ strings inside `marshal_as`, then copy all the strings from the temporary vector returned by `marshal_as` into xyz. If instead you did `std::vector<string> xyz; xyz.swap(marshal_as<string>(SomeCollectionOfSystemString));` then the array of strings which is the internal data storage of the temporary vector is transferred to `xyz` and no extra copies are made.
Ben Voigt
In C++0x, move constructor and move assignment syntax will make both methods efficiently turn over ownership of the vector content instead of copying it. Until then, though, calling swap is a common idiom to steal the content from a temporary.
Ben Voigt
My compiler crashes when I try to compile the above code. I think I will just have to implement the non-generic methods :-( until I have more time to troubleshoot it.
Scott P
That's entirely possible. A simple thing to try would be to make both `S` and `T` template arguments and not use generics.
Ben Voigt