将任何数据类型打包到vector <uint8_t> </uint8_t>中

时间:2014-11-04 20:43:23

标签: c++ vector stdstring

这个问题类似于

serialize any data type as vector<uint8_t> - use reinterpret_cast?

template <typename T>
inline void pack (std::vector< uint8_t >& dst, T& data) {
    uint8_t * src = static_cast < uint8_t* >(static_cast < void * >(&data));
    dst.insert (dst.end (), src, src + sizeof (T));
}

解压缩

template <typename T>
inline void unpack (vector <uint8_t >& src, int index, T& data) {
    copy (&src[index], &src[index + sizeof (T)], &data);
}

我正在尝试将任何类型的数据打包成字节数组。

问题1:我使用uint8_t *进行繁琐的实现,我希望选择矢量是最好的。

问题2:我无法使用上述函数正确打包std :: string。请告诉我上述函数在打包所有类型的数据类型时的舒适度

请告诉我如何将std :: string合并到上面的soluntion i e pack和std :: string into vector

我想打包的数据类型:

所有POD   的std :: string   矢量本身..

外部问题:

我想将这些类打包成一个字节数组

class StartPeerSessionRequest : public Request {

public:
    StartPeerSessionRequest();
    virtual ~StartPeerSessionRequest();
    void composeRequestwithHardCodeValues();
    vector<uint8_t> packRequestWithTemplate();

private:
    uint16_t    mProtocolVersion;
    uint16_t    mSessionFlags;
    uint16_t    mMaxResponseLength;
    string      mMake;
    string      mModel;
    string      mSerialNumber;
    uint8_t     mTrackDelay;
    string      mHeadUnitModel;
    string      mCarModelYear;
    string      mVin;
    uint16_t    mVehicleMileage;
    uint8_t     mShoutFormat;
    uint8_t     mNotificationInterval;

};

class Message {

public:
    Message();
    virtual ~Message();
    void composeMessage(vector<uint8_t> data, uint16_t opcode, uint16_t lengthOfData);

    uint16_t packetheader;
    uint16_t length;
    uint16_t request_response_id;
    uint16_t opcode;
    uint16_t checksum;
    vector<uint8_t> data;
}

我选择的字节数组数据类型是vector(uint8_t)

我想将其写入设备文件或通过蓝牙网络发送。我不想反序列化同一个类。我将收到一个响应,它又是一个字节数组,我需要最终将响应解包到另一个类

1 个答案:

答案 0 :(得分:4)

tl; dr:使用Boost.SerializationProtocol Buffers等序列化库。

广告1)矢量没问题。 编辑:但流会更好。

Ad 2)好吧,你不能用这种方式序列化间接对象,因为你只能获得指向实际数据的指针,而不是数据本身。而且您只能序列化plain old datastandard layout in C++11)个对象;或者更确切地说,不保证反序列化非普通旧数据/标准布局的对象将导致工作对象。 std::string(也没有任何其他容器)不是POD并且包含间接(std::string只是一种特殊的向量)。

无法将任意非标准布局对象序列化/打包到字节数组而无需特殊支持。您必须为每个这样的类型编写序列化和反序列化函数,或者您必须放弃字节数组要求并使用boost::any之类的东西来维护类型信息并在幕后为您正确调用构造函数和析构函数。请注意,boost::any本身是一个具有间接的非标准布局对象。

广告修改

  

我不想反序列化同一个类。

是的,你这样做。在连接的另一端。所以要么

  1. 另一端使用相同的结构,你必须编写序列化和反序列化,一个用于一端,另一端用于另一端,
  2. 另一端使用不同的结构(甚至可能使用不同的语言)并且你在两边工作,所以你必须写一个匹配的序列化和反序列化,或者
  3. 另一端由其他人编写,您必须编写序列化以使用特定的约定格式。
  4. 有数千种方法可以序列化每种类型。字符串可以序列化为长度,内容或内容以指定的终结符(通常为0字节)终止,整数(字符串大小为整数)可以序列化为不同的固定字节数,按不同的顺序(字节序),使用变量长度编码等。

    然后有变化。我看到你确实包含了协议版本。但是你还必须根据版本编写反序列化代码以执行不同的操作,这通常意味着无论如何都要逐个成员地执行(您希望在版本上独立输出相同的结构以保持下游代码正常)等。 / p>

    如果您没有决定协议,我建议您查看Boost.SerializationProtocol Buffers个库。

    • Boost.Serialization很好地粘合到现有对象中,但是特定于C ++并且只提供向后兼容性,即如果发送者发送版本2而接收者没有更新,则根本不会理解该消息。
    • 协议缓冲区要求以其特殊格式定义消息并从中生成C ++定义,但是大多数语言都有生成器并且它支持向前兼容性,即如果发送方发送版本2,接收方将理解已经存在的所有字段在版本1中,忽略那些不是。

    如果出于某种原因你不能使用它们(除非目标受到极大的限制,你应该能够;我使用的是同时使用Boost和Protobuf并在所有当前主要移动平台上运行的移动应用程序),至少阅读他们的技术说明,可能会查看代码,以便您知道如何很好地进行序列化。