Home > Back-end >  How to represent existing data as std::vector
How to represent existing data as std::vector

Time:03-17

I have to pass existing data (unsigned char memory area with known size) to the library function expecting const std::vector<std::byte>& . Is there any way to "fool" the library function to believe that it received a vector while operating on existing data?

  1. I have data from the old legacy as a pointer and size, not as a std::vector. Legacy C code allocates memory by malloc() and provides pointer and size. Please do not suggest touching the legacy code - by the end of the phrase I'll cease to be an employee of the company.

  2. I don't want to create temporary vector and copy data because memory throughtput is huge (> 5GB/sec).

  3. Placement new creates vector - but with the first bytes used for the vector data itself. I cannot use few bytes before the memory area - legacy code didn't expect that (see above - memory area is allocated by malloc()).

  4. Changing third party library is out of question. It expects const std::vectorstd::byte& - not span iterators etc.

It looks that I have no way but to go with temporary vector but maybe there are other ideas... I wouldn't care but it is about intensive video processing and there will be a lot of data to copy for nothing.

CodePudding user response:

Is there any way to "fool" the library function to believe that it received a vector while operating on existing data?

No.

The potential options are:

  1. Put the data in a vector in the first place.
  2. Or change the function expecting a vector to not expect a vector.
  3. Or create a vector and copy the data.

If 1. and 2. are not valid options for you, that leaves you with 3. whether you want it or not.

CodePudding user response:

Yes you can do this. Not in a nice safe way but it's certainly possible.

All you need to do is create a fake std::vector that has the same ABI (memory layout) as std::vector. Then set it's internal pointer to point to your data and reinterpet_cast your fake vector back to a std::vector.

I wouldn't recommend it unless you really need to do it because any time your compiler changes its std::vector ABI (field layout basically) it will break. Though to be fair that is very unlikely to happen these days.

CodePudding user response:

The problem is that std::vector is not a reference class like std::string_view or std::span. std::vector owns the managed memory. It allocates the memory and releases the owned memory. It is not designed to acquire the external buffer and release the managed buffer.

What you can do is a very dirty hack. You can create new structure with exactly the same layout as a std::vector, assign the data and size fields with what you get from external lib, and then pass this struct as a std::vector const& using reinterpret_cast. It can work as your library does not modify the vector (I assume they do not perform const_cast on std::vector const&).

The drawback is that code is unmaintainable. The next STL update can cause application crash, if the layout of the std::vector is changed.

Following is a pseudo code

struct FakeVector
{
  std::byte* Data;
  std::size Size;
  std::size Capacity;
}; 

void onNewData(std::byte* ptr, size_t size)
{
  auto vectorRef = FakeVector{ptr, size, size};
  doSomething(*reinterpret_cast<std::vector<std::byte>*>(&vectorRef)); 
}
  • Related