Using Embarcadero C++ Builder 10.3.
I have a DynamicArray<uint8_t> myData
object. I want to send/write its raw binary content (bytes) to a server using the TIdTcpClient
component. I'm going about it like this:
TIdTcpClient tcpClient1;
// Bla Bla Bla
tcpClient1->IOHandler->Write(rawData);
Where rawData
should be of type TIdBytes
or TIdStream
So basically, it boils down to the following: How to convert myData
object to a rawData
type of either TIdBytes
or TIdStream
?
First off, TIdStream
has not been part of Indy in a VERY VERY LONG time, which makes me wonder if you are using a very old version of Indy, not the one that shipped with C++Builder 10.3. Indy has supported the RTL's standard TStream
class for a very long time.
That being said...
TIdBytes
is an alias for System::DynamicArray<System::Byte>
, where System::Byte
is an alias for unsigned char
, which is the same size and sign-ness as uint8_t
(depending on compiler, uint8_t
might even just be an alias for unsigned char
).
So, the simplest solution, without having to make a separate copy of your data, is to simply type-cast it, eg:
tcpClient1->IOHandler->Write(reinterpret_cast<TIdBytes&>(myData));
This is technically undefined behavior, since DynamicArray<uint8_t>
and DynamicArray<Byte>
are unrelated types (unless uint8_t
and Byte
are both aliases for unsigned char
), but it will work in your case since it is the same underlying code behind both arrays, and uint8_t
and Byte
have the same underlying memory layout.
Alternatively, the next simplest solution, without copying data or invoking undefined behavior, is to use Indy's TIdReadOnlyMemoryBufferStream
class in IdGlobal.hpp
, eg:
TIdReadOnlyMemoryBufferStream *ms = new TIdReadOnlyMemoryBufferStream(&myData[0], myData.Length);
try {
tcpClient1->IOHandler->Write(ms);
}
__finally {
delete ms;
}
Or:
{
auto ms = std::make_unique<TIdReadOnlyMemoryBufferStream>(&myData[0], myData.Length);
tcpClient1->IOHandler->Write(ms.get());
}
Otherwise, the final solution is to just copy the data into a TIdBytes
, eg:
{
TIdBytes bytes;
bytes.Length = myData.Length;
memcpy(&bytes[0], &myData[0], myData.Length);
or:
std::copy(myData.begin(), myData.end(), bytes.begin());
tcpClient1->IOHandler->Write(bytes);
}