Подготовка блока данных для передачи по TCP (char*)
Есть блок данных. Его необходимо передать по сети TCP и для этого конвертировать в массив char. В настоящее время сделано с использованием языка С. Код ниже
std::vector<char> СreateCharVector_ForWrite(complex_float *InSig, uint32_t m_LenOnePack)
{
int32_t sizevect=0;
sizevect+=4; //char mark[]={'s','f','h','p'};
sizevect+=4;//uint32_t m_LenOnePack,
sizevect+=8*(m_LenOnePack);//размер входного массива
sizevect+=4; // размер всего int32_t sizevect
std::vector<char> m_vectDate;
m_vectDate.resize(sizevect);//создали вектор char заданной длины
char* buff=m_vectDate.data();
//!Поехали писать в память
int32_t tek_pos_char=0;
memcpy(buff+tek_pos_char,(const char*)&sizevect,4);
tek_pos_char+=4;
char mark[]={'s','f','h','p'};
memcpy(buff+tek_pos_char,(const char*)mark,4);
tek_pos_char+=4;
memcpy(buff+tek_pos_char,(const char*)&m_LenOnePack,4);
tek_pos_char+=4;
memcpy(buff+tek_pos_char,(const char*)&InSig,4*2*m_LenOnePack);
return std::move(m_vectDate);
}
Как можно сделать такое но с иcпользованием стандартной библиотеки С++.
Нашел вот такой пример
int main ()
{
std::stringbuf buffer; // empty buffer
std::ostream os (&buffer); // associate stream buffer to stream
// mixing output to buffer with inserting to associated stream:
buffer.sputn ("255 in hexadecimal: ",20);
os << std::hex << 255;
std::cout << buffer.str();
return 0;
}
но он не нравится потому что из него непонятно как выделить буфер заданного размера и потом его заполнить.
Ответы (1 шт):
Можно реализовать небольшой набор функций для выполнения подобных операций. К сожалению, в данный момент не могу добраться до своего кода, но написал немного упрощенную версию того, что использую я:
#include <cstdlib>
#include <vector>
#include <memory>
class DynBuffer
{
public:
constexpr DynBuffer(void const * buf, size_t n): buffer_(buf), size_(n) {}
constexpr size_t size() const { return size_; }
constexpr void const * buffer() const { return buffer_; }
private:
void const * buffer_;
size_t size_;
};
template<typename T>
constexpr size_t bufferSize(T const & obj)
{
return sizeof(obj);
}
constexpr size_t bufferSize(DynBuffer const & obj)
{
return obj.size();
}
template<typename ... Args>
constexpr size_t evalSize(Args && ... args)
{
return (bufferSize(args) + ...);
}
constexpr char const * rawBuffer(DynBuffer const & arg)
{
return static_cast<char const *>(arg.buffer());
}
template<typename T>
constexpr char const * rawBuffer(T const & arg)
{
return reinterpret_cast<char const *>(std::addressof(arg));
}
template<typename ... Args>
std::vector<char> & appendBuffersToVector(std::vector<char> & result, Args && ... args)
{
(result.insert(result.end(), rawBuffer(args), rawBuffer(args) + bufferSize(args)), ...);
return result;
}
template<typename ... Args>
std::vector<char> makeBuffer(Args && ... args)
{
std::vector<char> result;
result.reserve(evalSize(args...));
return appendBuffersToVector(result, args...);
}
С данным кодом Ваша функция превратится в нечто подобное:
std::vector<char> СreateCharVector_ForWrite(complex_float *InSig, uint32_t m_LenOnePack)
{
char mark[]={'s','f','h','p'};
auto buffer = makeBuffer(
int32_t (), //размер пакета. Можно использовать evalSize, но в данном случае будет дублирование кода
mark, //mark - массив, размер посчитается автоматически
m_LenOnePack, //размер также посчитается автоматически
DynBuffer(&InSig, 4 * 2 * m_LenOnePack)//передаем указатель и размеры "вручную", т.к. нет возможности посчитать размер автоматически
//вы уверены, что нужно брать адрес указателя InSig?
//скорее всего, имелось ввиду просто InSig, но я оставил как в оригинале
);
*reinterpret_cast<int32_t *>(buffer.data()) = buffer.size(); //записываем размер
return buffer;//std::move не нужен здесь - он только сделает хуже
}
Пример использования: https://wandbox.org/permlink/4RtAJzhTeZzyiI8H